Linux_基础编程day03

将近日学习Linux基础编程,系统编程,网络编程的word笔记搬运过来,图片无法直接粘贴,就丢失掉了。

日后工作学习中使用与扩充维护还是word笔记。

基础编程day03

内容简介:
学习目标:

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

         为什么提示找不到?

                   动态链接器需要知道动态库的路径

         优点:

                   可实现进程间的资源共享

                   程序升级简单

                   程序员可以控制何时加载动态库

         缺点:

                   发布时需要提供动态库

                   加载速度比静态库

 

1 makefile

      1 make是什么干什么

                   gcc-编译器

                   make-linux自带的构建器

                            构建的规则在makefile中

                   gcc的命令很长时,无法使用命令行来完成gcc

      2 makefile文件的命名

                   Makefile或makefile

      3 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命令,开始构建程序

      4 makefile的编写
              第一个版本

                            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

makefile工作过程:

                   第一行要用到a.o,b.o,c.o没有,就会向下寻找,所以下面生成.o文件的命令先执行如果只有a.o文件更新,那么执行make,只有a.o和app会重新生成。

                            缺点:冗余

 

                     makefile工作原理:

                            检测生成终极目标的依赖是否存在:

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声明为伪目标,不会进行更新检查

 

2 gdb调试

如何开始gdb调试

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

gdb常用命令
l(list)默认显示main函数所在的文件

设置显示的行数

set listsize / show listsize

         查看当前文件:

                  l n 显示n行

                  l 函数名

         非当前文件:

                  l 文件名:行号(函数名)

         直接回车默认是上一次输入的命令

        

b n设置断点;i b;d n;条件断点

                   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;n;c

                   r(run)程序从开始处运行

                   n向下走一行代码,遇到函数不会进入函数体内部,s会进入

                   c(continue)一次走多行

打印变量值p;ptype;display;i display;undisplay

         打印变量的值或类型

                   pi

                   ptypei

         自动打印变量的值

                   displayi 后面每次执行都打印i的值

         查看display的变量

                   idisplay

         取消display

                   undisplaynum num为I display显示的编号

进出函数体step;finish

         进入函数体(进入函数调用)

                   step回车

         出函数体(返回)

                   finish注意函数体内部不能再有断点,否则出不去

         start命令

                   程序会停在main下面的大括号

设置变量的值

                   setvar i = 5强行p array[i]; 打印array[5]的值

跳出当前for循环 until

                   until注意要把for循环中的断点都删除,否则跳不出去

 

3 文件IO

open
1 open传参需要使用的宏,所以多包含了头文件

         sys/types.h

         sys/stat.h

         fcntl.h

         unistd.h

         open是一个变参函数

         sprintf()格式化一个字符串

         返回文件描述符,成功,返回-1失败

2 open函数参数介绍

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库函数存在的意义有一项就是提高效率。

 

read:

         函数原型: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 文件读完了

write:

         函数原型:ssize_twrire(int fd, const void *buf, size_t count) ;

         参数:

                   fd:open返回值

                   buf:要写到文件的数据

                   count:srtlen(buf)buf中的有效字节数

         返回值:

                   失败 -1

                   >0写入到文件的字节数

你可能感兴趣的:(Linux)