日后工作学习中使用与扩充维护还是word笔记。
1 makefile简单编写
2 makefile中的变量
3 makefile中的函数
4 掌握gdb相关调试命令
5 了解 pcb进程控制块(结构体)和文件描述符,虚拟地址空间
6 linux系统io函数的使用
open/read/write/lseek
7 了解阻塞非阻塞 阻塞就像是模态对话框
是什么—干什么—怎么用—优缺点
makefile
工作过程,目标依赖命令,变量,$,%,函数wildcard, pastsubst,.PHONY:clean
gdb
gcc–g, l,b,r,n,p,display,step,finish,until
文件IO
fd,open, RDONLY…, mode, read, write
动态库:
是什么
二进制的源代码
干什么
加密工作,保护知识产权
把源代码打包,和测试程序一起生成可执行文件
怎么用
静态库:
1生成.o文件 gcc a.c b.c -c
2打包 ar rcs libtest.aa.o b.o
3使用 编写测试程序 gcc test.c –L ./lib –l test
动态库:
1生成.o gcc a.cb.c –fpic
2打包 gcc –shareda.o b.o –o libtest.so
3使用 环境变量,文件列表
静态库
优点:
静态库打包到应用程序中,加载速度快
发布程序不需要提供静态库,移植方便
缺点文件列表
浪费系统资源,会加载重复的库,浪费内存
更新,部署,发布麻烦
动态库
gcc test.c –L ./ -l test –o app
./app
app制作好了之后,动态库没有打包到app中
./app动态库也不会被加载,当程序调用到动态库中的函数的时候,才会被加载
程序提示加载不到,是在判断能否找到动态库,此时还没有加载
动态加载器ld-linux-x86xxxxxxx.so
为什么提示找不到?
动态链接器需要知道动态库的路径
优点:
可实现进程间的资源共享
程序升级简单
程序员可以控制何时加载动态库
缺点:
发布时需要提供动态库
加载速度比静态库慢
gcc-编译器
make-linux自带的构建器
构建的规则在makefile中
当gcc的命令很长时,无法使用命令行来完成gcc
Makefile或makefile
gcca.c b.c c.c –o app
三部分:目标,依赖,命令
目标:依赖
(tab缩进)命令
app:a.c b.c c.c
gcc a.c b.c c.c –o app
makefile中有一条或多条规则组成
完成makefile的制作后,使用make命令,开始构建程序
app:a.cb.c c.c
gcca.c b.c c.c –o app
缺点:效率低,修改一个文件,所有文件会被重新编译
app:main.oa.o b.o c.c
gcca.o b.o c.o –o app
a.o:a.c
gcca.c –c
b.o:b.c
gccb.c –c
c.o:c.c
gccc.c –c
第一行要用到a.o,b.o,c.o没有,就会向下寻找,所以下面生成.o文件的命令先执行如果只有a.o文件更新,那么执行make,只有a.o和app会重新生成。
缺点:冗余
检测生成终极目标的依赖是否存在:
1依赖不存在:向下搜索下边的规则,如果规则是用来生成查找的依赖的,执行规则中的命令。
2依赖存在:做时间的对比,判断是否需要更新,发现a.o的时间早于a.c,说明a.c修改过了。目标的时间<依赖的时间,就会更新
3 makefile会有自己内建的一些规则,不写gcc a.c –c,也能在需要时生成a.o
自定义变量:obj=a.o b.oc.o 没有数据类型
变量的使用:aa=$(obj) //类似解引用
makefile自带的变量:都是大写,程序用定义的尽量用小写
CPPFLAGS=
CC
自动变量:
$@:规则中的目标
$<:规则中的第一个依赖
$^:规则中所有的依赖
只能在规则的命令中使用
obj=a.o b.o c.o
target=app
$(target):$(obj)
gcc$(obj) –o $(target)
%.o:%.c
gcc–c $< -o $@
第一次a.o没有,所以%被替换为a,a.o:a.c,$<是规则中的依赖a.c,$@是规则中的依赖,是a.o
第二次b.o没有,重复上面的情况
makefile中注释是#
缺点:不灵活,可移植性差,
makefile中所有的函数都有返回值
提高可移植性,使用makefile函数:
查找指定目录下指定类型的文件:
src= $(wildcard ./*.c) #查找当前目录下所有.c文件,赋值给src
匹配替换:
obj= $(patsubst %.c, %.o, $(src) ) ;将.c替换为.o,从src中来找文件,匹配%
src = $(wildcard ./*.c)
obj = $(patsubst %.c, %.o, $(src) )
target=app
$(target):$(obj)
gcc$(obj) –o $(target)
%.o:%.c
gcc–c $< -o $@
添加项目清除的功能:让make生成不是终极目标的目标
clean:
# rm *.o app
rmobj target –f # -f强制执行删除命令,不提示
在makefile命令前加-,如果当前命令执行失败,依然向下执行其余的命令
反之,如果不加-,那么执行失败就停下来了
在make时,需要makeclean才会执行clean后面的规则,生成clean。如果当前目录中已经有了clean文件,那么不会执行clean后面的命令
.PHONY:clean 将clean声明为伪目标,不会进行更新检查
1 .cà.o gcc命令加 -g
gcc a.c b.c c.c–o app
gcca.c b.c c.c –o app –g
-g会保留函数名和变量名
2 启动gdb
gdb可执行程序的名字
gdbapp
给程序传参: setargs xxx xxx
argc参数的个数
char *argv[]
几个参数是:可执行程序的名字,启动应用程序时传递的参数./a.out abc def 000 后面几个就是传递给argv[]的参数argv[1] = abc argv[2]=def
设置显示的行数
set listsize / show listsize
查看当前文件:
l n 显示n行
l 函数名
非当前文件:
l 文件名:行号(函数名)
直接回车默认是上一次输入的命令
b20 在第20行设置断点
bfunc 在func函数处设置断点
b文件名:行号
b文件名:函数名
i(info) b 查看设置过的断点
d(del) num num是断点的编号,通过i b查看
dn1-n2 删除范围内的断点
断点enable和disable
dis num num是断点的编号,使断点无效
enb num 使断点有效
条件断点
b7 if i==10 在7行打断点,在i==10时才停下来
r(run)程序从开始处运行
n向下走一行代码,遇到函数不会进入函数体内部,s会进入
c(continue)一次走多行
打印变量的值或类型
pi
ptypei
自动打印变量的值
displayi 后面每次执行都打印i的值
查看display的变量
idisplay
取消display
undisplaynum num为I display显示的编号
进入函数体(进入函数调用)
step回车
出函数体(返回)
finish注意函数体内部不能再有断点,否则出不去
start命令
程序会停在main下面的大括号
setvar i = 5强行p array[i]; 打印array[5]的值
until注意要把for循环中的断点都删除,否则跳不出去
sys/types.h
sys/stat.h
fcntl.h
unistd.h
open是一个变参函数
sprintf()格式化一个字符串
返回文件描述符,成功,返回-1失败
int open(const char *pathname, int flags) ;
intopen (const char *pathname, int flags, mode_t mode);
参数:
flags:
必选项 O_RDONLY,O_WRONLY,O_RDWR
可选项:
创建文件:O_CREAT如果不存在就创建它
检测文件是否存在O_EXCL存在返回-1
追加文件:O_APPEND把文件指针移动到文件尾部
文件截断:O_TRUNC把文件清空,删除原有文件
设置非阻塞:O_NONBLOCK read, write要用
mode_t:指定文件权限
指定文件的权限 0777
最终结果是mode | ~umask
umask是掩码,对文件起保护作用,可以设置默认是0002
如果没有指定权限,那么创建出来的文件权限是随机的!(创建时在栈区找的8进制值,是随机找的)
作业,有一个文件,open打开,数据读出来,read,读出的数据写到另外一个文件
系统函数与C库函数谁的速度快?不一定,C库函数有内存缓冲区,而系统函数read,write没有缓冲区,直接操作磁盘,速度可能更慢。C库函数存在的意义有一项就是提高效率。
函数原型:ssize_t read(int fd, void *buf, size_t count) ;
参数:
fd:open的返回值,文件描述符
buf:缓冲区,存储要读取的数据
count:缓冲区能存储的最大字节数sizeof(buf)
size_t:unsigned int无符号整型值
ssize_t:有符号的
返回值:
失败 -1
成功:
>0读出的字节数
=0 文件读完了
函数原型:ssize_twrire(int fd, const void *buf, size_t count) ;
参数:
fd:open返回值
buf:要写到文件的数据
count:srtlen(buf)buf中的有效字节数
返回值:
失败 -1
>0写入到文件的字节数