Linux C下gdb调试工具简记

1、gdb调试工具
gcc -g -o sum sum.c
gdb ./sum
调试命令:
file –> 指定调试文件
list/l –> 查看原代码(默认10行)
list n –> 列出n附近的10行代码
run/r –> 运行
break/b –> 设置断点 如: b main b 10
info breakpoints/i b –> 查看所有的断点
delete breakpoints <Breakpoint Number>/d b number–> 删除断点
next/n –> 单步运行下一行代码(遇到函数调用不会进入函数内运行)
step/s –> 单步运行下一行代码(遇到函数调用会进入函数内运行)
print/p
set variable 变量名=值
until/u 26 –> 跳到某行
finish –> 跳出函数(finish不能简写成f)
quit/q –> 退出gdb
display /i $pc
同时显示c代码和汇编代码

disassemble 函数名
查看指定函数的反汇编代码

1) 查看寄存器
info registers或者i r
查看寄存器的情况
info all-registers或者i r a
查看所有寄存器的情况
info registers eip或者p $eip
查看指定寄存器

2) 查看内存
(gdb) x /x 0x80040000 # 以16进制显示指定地址处的数据
(gdb) x /s 0x86468700 # 以字符串形式显示指定地址处的数据
(gdb) x /d 0x86468700 # 以十进制形式显示指定地址处的数据
(gdb) x /o 0x86468700 # 以八进制形式显示指定地址处的数据
(gdb) x /t 0x86468700 # 以二进制形式显示指定地址处的数据
(gdb) x /d $ebp-0x8 # 以十进制形式显示寄存器ebp中的值减去0x8后地址处的数据

x 按十六进制格式显示变量。
d 按十进制格式显示变量。
u 按十六进制格式显示无符号整型。
o 按八进制格式显示变量。
t 按二进制格式显示变量。
a 按十六进制格式显示变量。
c 按字符格式显示变量。
f 按浮点数格式显示变量。

3) 修改寄存器的值
(gdb) set $v0 = 0x004000000
(gdb) set $epc = 0xbfc00000

4) 修改内存的值
(gdb) set {unsigned int}0x8048a51=0x0
2、objdump工具
objdump -xd sum.o
objdump -xd sum
将.o目标文件或可执行文件进行反汇编

Linux C 学习笔记 二

缓冲区

在程序和输出设备间缓冲数据fflush

 

库函数的使用

静态库:编译时刻将库代码链接到应用程序生成文件较大

共享:程序运行时载入共享库代码

动态:程序中语句需要使用时载入库代码

 

静态库的制作

1、模块化编写库模块

fun.c fun.h 就是说把需要实现的模块分开来写,而不是写在main里面

2、编译生成目标文件

fun.o

gcc -c -o obj/fun.o src/fun.c -Iinclude

3、使用目标文件生成静态库文件

libfun.a

ar -rc 库文件名 目标文件名

eg: ar -rc lib/libfun.a obj/fun.o

 

4、将库文件链接到主程序的目标文件中

libfun.a+main.o

gcc -o bin/main obj/main.o -Llib -lfun

-L 库文件目录路径

-l 库文件 去掉lib 和扩展名

共享库

1、模块化编写库模块

fun.c fun.h 就是说把需要实现的模块分开来写,而不是写在main里面

2、编译生成目标文件

fun.o

gcc -c -o obj/fun.o src/fun.c -Iinclude

3、生成共享库文件

libfun.so

gcc -fPCI -shared -o lib/libfun.so obj/fun.o

4、将库文件链接到主程序目标文件

libfun.so + main.o

gcc -o bin/main obj/main.o -Llib -lfun

5、将共享库配置到当前系统中

1)将共享库拷贝到系统默认库路径下

lib/, /usr/lib

(2)配置当前系统的环境变量

export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:lib/

当简称相同的时候,扩展名不一样时,优先选择.so文件

例: libfun.so libfun.a共存优先选择.so文件

 

如何批量化的执行编译过程Makefile

批量化执行文件处理过程

desk:wood nail

make up

wood:tree

cut

nail:iron

burn

使用make执行Makefile文件

默认执行名为Makefile的文件

-f 制定执行的文件名 make -f Makefile.shared

 

当你修改了其中之一的文件时,再次执行make时,它会只能比较文件,只执行编译最新的文件

当你就是想要编译一下的话,那可以编写clean:项目

clean:

rm -rf obj/main.o obj/fun.o

rm -rf bin/main

使用make clean执行清理工作

警告提示

-Wall 打开所有类型语法警告 ,建议使用

-Wchar-subscripts 如果数组使用char类型变量作为下标值,则发出警告

警告warnin

编译有可能成功,会生成输出文件

错误error

语法错误,编译失败

1、编译错误一般为语法错误,容易修改

根据编译器的提示修改错误

追踪法

2、运行错误一般为逻辑错误 int *p=100 把指针强制置为100

printf(“%d”,*p);

则会报运行时错误

a、标记法

printf(“message\n”);

b、添加删除法(注释法)

c、调试法

借助调试工具进行调试debug

gdb工具+vi +gcc/g++ =Linux 下三大工具链

在使用GDB调试工具时要多加一个参数 -g

gcc -g -o sum sum.c

gdb ./bin/sum

 

gdb工具

list/l列出代码

run/r执行到结果

break/b 设置断点

info breakpoints/i b 查看所有断点

delete breakpoints db bumbers删除断点

next/n 单步运行不进入行数

step/s 进入函数

print/p 查看变量值

set variable 变量名=

until/u 直接跳到某行

display 跟踪变量的值

 

代码优化

-O1 线程跳转和延迟退栈优化

-O2 包含O1并进行额外的调整工作

-O3 循环展开以及和处理器特性相关的优化

&&&

&& 逻辑与 0为假 非0为真

& 按位与

|| 逻辑或

|按位或

 

 

C 语言数据类型,只有四种数据类型,C语言是强类型语言,必须定义类型

整型

浮点型

指针

聚合类型(数组和结构)

 

整型

字符(char),短整型(short),整型,长整型(long)

char 0~255

singed char -127~127

unsigned char 0~255

char

数据类型与整型的联系

ASCII码表

char ch=’9′

char ch=9;

进制类型

十进制 100

八进制 0100 —-64

十六进制 0x100 —>256

二进制 0b100 —->4

枚举类型

enum

 

溢出问题,造成数据紊乱

正溢出:超过了最大范围

负溢出:小于最低下限

 

a为整数,b为整数 2者皆为溢出

问:如何判断a+b不溢出

if(a>INT_MAX-b)

{

溢出?

}

标识符

变量名

函数名

宏名

Linux C 学习笔记 一

嵌入式Linux C

www 原则:what why how

编译型语言

源代码 –>编译器–>二进制文件

解释型语言

shell html

 

<<C Programing language>>

 

语言关注度排行

c

java

c++

objective -c(oc)

main 函数—>程序的入口

程序一个入口,一个出口(多个位置)

 

main函数的一些写法

main() —不推荐

main(void) —不推荐

void main() —不推荐

int main(void) —标准

int main(int,char**) —没有参数名,不推荐,二级指针

int main(int,char*[]) —不推进啊

int main(int argc,char **argv) —不推荐

int main(int argc,char *argv[]) —标准

int main(int argc,char argv[],char *env[]) –env环境变量

 

argc 代表命令行参数个数,

argv 参数列表

 

文件类型

.c c语言源文件source

*.cpp *.cxx c++语言源文件

.h 头文件header

.o 目标文件object,已经过编译的二进制代码,但未链接

*.so *.a 库文件libraryfor Linux.a问静态库 .so 动态库、共享库

*.dll (for windows)

.png 杂项

.jpg

.ini

 

 

项目结构

src 源文件

include/inc 头文件

obj 目标文件

lib 库文件

bin 二进制可执行文件

 

 

gcc

-o 指定输出文件名

-E 在预处理期完成后就停止编译过程,得到 .i文件

-S 在编译期完成后停止编译过程,*.s

-c 在汇编期完成后停止编译过程,*o

-I 指定头文件的路径

 

多行注释匹配原则

与上一个距离最近且未被匹配的符号进行匹配

多行注释不可嵌套

需要注释多行注释可使用条件编译

条件编译(预处理指令)

#if 0

/*写在里面的都将被删除

#endif

c 语言有两种条件逻辑,一种是0 一种是非0

 

#include <头文件>

#include “头文件”

1C标准库函数的头文件

2、由程序员自定义的头文件

3、第三方的库的头文件

 

<>和“”区别在于在编译的过程中,头文件的搜索路径不同

<> 优先从系统头文件路径开始搜索

“”优先从用户制定的头文件路径开始搜索

 

预处理

gcc -E -o example.i example.c 指到这个预处理期过程就停止,得到的就是

执行的是文本操作,

a.展开include指令 ,把所有包含的头文件都进行引导

b.条件编译 解析#if的内容,将逻辑假内容删除

c.宏展开

#define 定义的宏名都替换成其相应的值

d.删除注释

c语言中定义两个相同的变量,会报错,从定义

 

 

编译阶段

把已经预处理后的代码编译生成汇编代码

gcc -S -o example.s example.i

汇编阶段

编译汇编代码 vi 使用的是asscii格式查看文本,可以使用 bvi安装插件查看二进制代码

gcc -c -o obj/helloword.o src/helloword.c

链接阶段

将目标文件和库文件、其他目标文件进行链接,生成可执行文件

gcc -o bin/helloword obj/helloword.o

 

C语言的算法

有穷性,确切性,输入,输出,可行性

 

-1%256= 255 ==> (-1+256)%256=255

 

printf()函数

%d 有符号十进制整数 int

%c 字符 char ‘a’

%s 字符串 char * “aaaa”

%o 有符号八进制

%x 十六进制

%p 地址指针 0xffffffff

%f 浮点数 float

32位系统—> 寻址空间为32bits —>实际操作只有3Gb

0x0000 0000 0000 0000 0000 0000 0000 0000

…..

0xffffffff ………

 

0x0000 0000

用户空间

0xc000 0000

内核空间

0xffff ffff

 

所有进程运行在内核态

 

库函数的使用

%s/;$/\n{\n}/g 替换全部的;结尾的 然后换行{换行} 替换全部

 

 

执行编译

gcc -c -o obj/fun.o src/fun.c -Iinclude

gcc -c -o obj/main.o src/main.c -Iinclude

-Iinclude 表示-I后面进阶自己写的头文件的目录

执行链接

gcc -o bin/main obj/main.o obj/fun.o 

Linux 学习笔记 八

参数,选项

模拟 ls -a

ls -l

ls -la

eg:

#!/bin/bash

if [ $# -lt 2 ]

then

echo “the grgument less than 2”

exit 1

fi

case $1 in

-a)

args=” -a $2″

;;

-l)

 

args=” -l $2″

;;

-al|-la)

args=” -al $2″

;;

*)

echo “option is error”

exit 2

;;

esac

ls $args

 

专门处理参数选项的命令

getopts

 

输入输出

echo

printf 带格式输出

eg:

#!/bin/bash

var=3.141592654

str=”hello word”

printf “info:%+016s\n” “$str”

printf “data:%+016f\n” “$var”

输入

read

<

文件描述符

一个编号就代表了一个文件

标准输入STDIN 0

标准输出STDOUT 1

标准错误 STDERR 2

 

今天早上睡着了,都没有记录笔记。。。累死个人~!!!

 

type 查看命令是内部命令还是外部命令

 

 

exec 参数

功能:当SHELL 执行到exec语句时,不会去创建新的子进程,而是转去执行制定的命令,当指定的命令执行完时,该进程,也就是最初的SHELL 就终止了,exec 后面的语句就不再执行了。

重定向来至SHELL 脚本内部的文件描述符

 

>a.txt 也是清空a.txt

 

eval SHELL特殊字符通过变量替换或命令替换被插入时,要用到eval

eg:

OUTPUT=”>a.txt”

eval echo hello $OUTPUT

 

readonly 定义只读变量 使用unset不能修改,var=new 也不修改不了

 

shift 语句

shift 语句在每使用一次时,位置变量向左移动一位,直到减为0

wait 语句

SHELL等待后台启动的所有子进程结束,返回值总为真

eg:

 

#!/bin/bash

date

 

sleep 5 &

 

cal

echo “finished”

 

wait

 

set 语句

shell脚本的任何地方启动或取消调试

getopts 处理符合的选项

test 条件判断

trap 和信号有关的东西

 

内置符号命令

. 执行文件

:空操作,返回状态值为0

&后台工作

$()命令替换

(())算术表达式计算,let(被括起来值中包含=时使用)

$(())算术扩展(不用于被括起来的值中,包括=的情形)

[]同test

[[]]条件表达式 类似与[]

expr 也是算术运算

 

shell 分组的方法

() 新开一个小shell 顺序执行()里面的指令,(cmd1;cdm2;cdm3;)

{} 在当前的SHEL顺序执行当前的SHELL命令{cmd1;cmd2,cmd3;

 

函数

函数名 (){

函数体

 

function 函数名 () {

函数体

}

 

 

eg:

#!/bin/bash

 

function fun(){

date

echo “this is a function!”

cal

}

 

fun

 

 

 

不同文件内函数调用

eg

 

function2.sh

 

#!/bin/bash

 

i=0

compare(){

num1=$1

num2=$2

if [ $num1 -eq $num2 ]

then

echo “the two numbers is equal”

return 0

elif [ $num1 -lt $num2 ]

then

echo “the numbers of:$num2 bigest to the numbers of :$num1”

i=$num2

return 1

else

echo “the numbers of:$num1 biggest to numbers of :$num2”

i=$num1

return 2

fi

}

 

 

 

 

 

function3.sh

#!/bin/bash

. function2.sh

compare 10 20

 

 

调试

格式 bash –选择项

-n 测试SHELL 脚本的语法结构,只读取不执行

-x 进入跟踪方式,执行命令时把命令和它们的参数显示出来

-e 非交互式,如果一个命令失败就立即推出

-l交互式

-k从环境变量中读取命令的参数

-r 限制方式,不能执行如下操作

-t 执行名后退出

-u 置换时把为设置的变量看作出错

-v verbose 当读入SHELL输入行时把他们显示出来

set 使用set命令,用户可以在shell脚本的任何地方启动或取消调试

启动:set –选择项

禁止:set +选择项

eg:

#!/bin/bash

num=1

sum=0

set -x

while [ $num -le 5 ]

do

sum=$(($sum+$num))

num=$(($num+1))

done

set +x

 

echo “sum:$sum”

 

信号处理

查看所有信号 kill -l

ps -e里出所有进程

ps -ef 所有进程的详细信息

 

trap – 重置所有信号

 

Linux 学习笔记 七

实现算数运算或者实现SHELL 命令

 

VAR=date 注意 为esc下面的反引号

echo $VAR  则输出的是date命令的输出

 

let var=1+1

echo $var 则输出结果为2

var=((1+1))

echo $var    则输出结果也是为2

 

引用

”  单引号   只要出现单引号里面,则特殊含义全部去除

\      如果下一个字符有特殊含义,则使用\ 即屏蔽其特殊含义

 

echo -e “hello \t word”             其中-e选项可以使转义字符生效

echo ‘it’s Friday’         错误 因为它会把其判断成两个

echo ‘it\’ 也是不行的,因为‘’会吧所有的转义的字符全部去除其特殊含义  会输出it\

echo it\’s Friday   正确输出

 

cal 7 2013 打印制定年份月份  默认打印当月  输入一个数字就是默认打印一年  cal 2013

双引号

删除除以下字符外所有其他字符的特殊含义

$ 用于变量替换

用于命令替换

\$

\”

\\

 

流程控制

test 测试

文件测试

字符串测试  =        != -z    -n

数字测试

测试时使用逻辑操作符

混合条件

 

九大文件类型

-e    文件存在则为真

-r     可读文件

-w   可写文件

-x    可执行文件

-s    非空文件

-d    目录文件

-f    普通文件

-c    字符文件

-b    块文件

-z    字符串为空为真

-n    字符串为非空为真

 

 

eg:

#!/bin/bash

echo -n “please input a filepath:”

read filepath

if test -d $filepath #[ expression  ]

then

echo “$filepath is a dir!”

elif [ -f $filepath ]

then

echo “$filepath is a file!”

else

echo “others!”

fi

 

#!/bin/bash

echo “please input a dir”

read filepath

if [ $filepath = $HOME ]

then

echo “this is home dir”

else

echo “this is the dir :$HOME”

fi

 

数值测试

-eq: 等于

-ne: 非等于

-lt:   小于

-gt:  大于

-le:  小于等于

-ge: 大于等于

 

eg:

#!/bin/bash

echo -n “please input two numbers:”

read num1 num2

if [ $num1 -eq $num2 ]

then

echo “$num1 = $num2 ”

elif [ $num1 -lt $num2 ]

then

echo ” $num1 < $num2″

else

echo “$num1 > $num2”

fi

 

逻辑测试

-a 逻辑与

-o 逻辑或

! 逻辑否

优先级 !> a >o

 

eg:

#!/bin/bash

echo -n “please input a file:”

read filepath

if [ -x $filepath -a -r $filepath -a -w $filepath ]

then

echo “read write and exec”

else

echo “no”

fi

混合条件

&&      与

||      或

 

case 语句

#!/bin/bash

echo -n “your a numbers:”

read number

case $number in

“BMW”)

echo “you enter one”

;;

“AUDI”)

echo “you enter AUDI”

;;

“BENZ”)

echo “it’s BENZ”

;;

*)

echo “others”

esac

         #!/bin/bash

echo -n “please input a string:”

read str

case $str in

[a-zA-Z]*)

echo “your string in a-z”

;;

#     [A-Z])

#            echo “your string in A-Z”

#            ;;

*)

echo “others”

;;

esac

 

循环

for循环

while循环

until循环

select循环

break     and continue 循环

 

for循环

一般格式

for 变量名 in 列表 for I in 0 1 2 3 4 5

do                 do

命令                    ecjo $i

done                    done

 

 

eg:

#!/bin/bash

counter=1

for num in 0 1 2 3 4 5 6 7 8 9

do

echo “num $counter:$num”

counter=$(($counter+1))

done

echo “for finished”

 

eg:

#!/bin/bash

sum=0

for((i=1;i<=100;i++))

do

sum=$(($sum+$i))

done

echo “sum is $sum”

eg:  读入一个目录,查找该目录下所有的软链接文件,并排序输出到forSoftLink文件

#!/bin/bash

echo -n “please input a dir:”

read dir

counter=1

for i in find $dir -type l  #查找目录下所有链接文件 find -type l

do

echo “file$counter:$i”

counter=$(($counter+1))

done | sort > forSoftLink

while 循环

一般 格式

while 条件         x=0

do                 while[ $x -lt 10 ]

命令                    do

done                           echo $x

x=$(($x+1))

done

 

打印是个200到500的随机数

eg:

#!/bin/bash

i=0

while [ $i -lt 10 ]

do

echo “numbers is :$(($RANDOM%(301)+200))”

i=$(($i+1))

done

until循环 条件不满足进入循环

EG:#!/bin/bash

i=0

until [ $i -gt 10 ]

do

num=$(($RANDOM%301+200))

i=$(($i+1))

echo “$num”

done

 

 

select 循环

#!/bin/bash

PS3=”which is your favorite:”

select car in “BMW” “JEEP” “HONGQI” “BENZ”

do

echo “your favorite car is $car!”

break

done

 

参数

读出并解释各种选项、参数

./filename 1 2 3 4 5

后面跟的就是参数

命令行参数:是一种在调用SHELL的命令行中按照各自的位置决定的变量,实在程序名之后输入的参数 位置参数之间以空格分隔,$1 取地一个参数 $2 取第二个参数  $0 是当前SHELL 程序名

EG:

#!/bin/bash

if [ $1 -eq $2 ]

then

echo “$1 = $2”

elif [ $1 -lt $2 ]

then

echo “$1 < $2”

else

echo “$1 > $2”

fi

 

特殊变量

查看位置参数的数量      $#

所有位置参数的内容      $*

命令执行后返回的状态 $?

当前的进程号:       $$

后台执行的最后一个进程号:$!

 

1 12 13 14 15 16 20