《Linux应用程序开发基础知识.pdf》由会员分享,可在线阅读,更多相关《Linux应用程序开发基础知识.pdf(68页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、L in u x应用程序开发基础知识目录1.C语言基础1.1.数据类型1.4.特殊字符的表示方法:1.5.格式化字符串1.6.指针与数组1.7.结构体1.8.tvpedef-自定义类型名1.9.函数和宏1.10.ANSI标准头文件2.预处理3.使 用GCC编译程序4.使 用adb调试程序5 .Linux程序开发基础5.1.路径5.2.阵文件5.3.预处理5.4.系统 调 用(system call)6.文件处理7.Linux环境编程7.1.参数选项7.2.环境变量7.3.时间7.4.临时文件7.5.用户信息7.6.II志信息8.进程8.1.进程状态9.串口编程9.1.常用函数9.2.设置串口属
2、性9.3.c iflaa输入标志说明9.4.c oflaa输出标志说明9.5.c cflaa控制模式标志说明9.6.c cc”控制字符说明9.7.c Iflaa木地模式标志说明9.8.卜.一介绍一些常用*I I属性的设置方法。1 0.安 全1 0.1.内核漏洞介绍11.数 据结构(Data Structure)1 1.1.基础概念1 1.2.线性数据结构12.网络编程12.1.TCP/IP协议分析1 2.2.入门示例程序13.存储器寻址14.设备驱动程序开发15 .字符设备驱动程序1 5.1.设备号15.2.设备号的分配和释放1 5.3.一要的数据结构15.4.读和写16.PCI设备17.内核
3、初始化优化宏18.访问内核参数的接II1 9内核初始化选项2 0内核模块编程2 0.1.入门2 0.2.为模块添加描述佶息2 0.3.内核模块处理命令介绍2 1.网络子系统21.1.sk buff 结构21.2.sk buff结构操作函数 device 结构2 1.4.网络设备初始化2 1.5.网络设备与内核的沟通方式2 1.6.网络设备操作层的初始化2 1.7.内核模块加载器21.8.虚拟设备21.9.8139too.c 源码分析2 1.1 0.内核网络数据流2 2.备忘录List of Tables1.1.特殊字符的表示方法Chapter 1 .C 语言基础Table of Content
4、s1.1.数据类型1.2.关键字1.3.变量等级1.4.特殊字符的发示方法:1.5.格式化字符串1.6.指针与数组1.7.结构体1.8.typedef-自定义类型名1.9.函数和宏1.10 ANSI标准头文件Linux是使用C 语言开发的,基于Linux平台的应用程序开发,C 语言是首选的开发语言。本章记录C 语言的基本概念和基础知识。1.1.数据类型整数类型(int),各种整数数制表示法:d d d,十进制表示法,d 为 09 的整数,但不能以0 开头。如:123,345 O ooo,八进制表示法,以0(数字0)开头,。为07的整数。如:010(八进制)=8(十进制),014(八进制)=12
5、(十进制)。O xhhh,十六进制表示法,以Ox或 0X 开头,h 为09、A、B、C、D、E、F。如:0 x10(十六进制)=16(十进制),OxA(十六进制)=10(十进制).以L 或 I 结尾的数表示长整数(long int),编译器会以3 2 位空间存放此数字,但 GCC默认是以3 2 位存放整数,所以此表示法在Linux下没什么作用。1 .2.关键字关键字是C 语言本身保留使用的,不能用于变量和函数名。a u t od o u b l ei n ts t r u c tb r e a ke l s el o n gs w i t c hc a s ee n u mr e gi s t
6、 e rt y p e d e fc h a re x t e r nr e t u r nu n i o nc o n s tf l o a ts h o r tu n s i gn e dc o n t i n u ef o rs i gn e dv o i dd e f a u l tgo t os i z e o fv o l a t i l ed oi fs t a t i cw h i l e1 .3.变量等级 a u to,内部变量,在函数内部声明。只能在函数内部使用,它的生命周期从调用函数开始,到函数执行完时消失。内部变量以堆栈存放,必须在函数执行时才会存在,这种方式称为声明。
7、auto可省略。如:a u t o i n t i =0;/*可写成 i n t i =0;*/内部变量的优缺点:。内部变量只在函数内有效,能提高函数的安全。内部变量在函数结束时消失,不会长期占用内存空间,能提高内存的利用率。内部变量的缺点是生命周期短,函数运行结束后不能保留。static a u to,内部静态变量,在函数内部定义,auto也可省略。内部静态变量以固定地址存放,编译时就已分配置内在空间,这种方式称为定义。由于有固定地址,函静态变量不会随函数的结束而消失。static变量会一直保存在内存空间中,当函数再次执行时,上次保留的使用静态变量可以继续使用。如:s t a t i c i
8、 n t i =0;e x te rn,外部变量,是在函数外定义的变量,可被多个函数存取。在外部变量定义覆盖范围之内的函数内可以自由使用外部变量。不在外部变量定义覆盖范围之内的函数要使用外部变量就要先使用extern关健字来声明外部变量。i n t i ;/*外部变量定义,在ma i n 函数外*/i n t ma i n(v o i d)(i =1;/*ma i n。函数位于外部变量i 定义的下面,不用声明可直接使用*/p r i n t f (/%d n,/,i);)不在外部变量定义覆盖范围之内的函数要使用外部变量就要先使用extern关健字来声明外部变量。i n t ma i n(v o
9、 i d)(e x t e r n i n t i ;/*外部变量i 在ma i n ()函数之后定义,需用e x t e r n 关键字声明后才能使用*/i =1;p r i n t f(%d n ,i);)i n t i;在另外的程序文件中我们也可以通过扩展声明使用其它程序文件中的外部变量。程序 1 h e llo,cS i n c lu d e i n t ma i n(v o i d)(e x t e r n i n t i;/扩展声明外部变量i =3 3 3;p r i n t f (,%d n,/,i);e x t e r n d e s (v o i d);扩展声明外部函数d e
10、 s();)i n t i;外部变量定义程序 2 h e llo l.cS i n c lu d e e x t e r n i n t i;扩展声明其它程序文件中的外部变量v o i d d e s ()(i+;p r i n t f (9 6 d n,i);)编译d e b i a n:/c#g c c h e llo,c h e llo l.cd e b i a n:/c#./a.o u t3 3 33 3 4外部变量有效范围总结:。由外部变量定义的位置开始,至文件结尾。不在有效范围内的函数,也可通过extern扩展声明使用定义的外部变量,且可在多个函数中使用。注意:在各函数中使用的外部
11、变量是一样的,对该变量的修改会影响到其它函数内的同变量。可用extern扩展声明使用另外一个程序文件中的外部变量。外部变量的优点是生命周期长,可在函数间共享数据和传输数据。缺点是变量安全性较低,但可通过合理设置外部变量的有效范围提高安全性。static extern,外部静态变量,在函数外部定义,只供单一程序文件使用,即使其它程序文件定义了同样名称的变量,编译器也把它当成另外一个变量处理。外部静态变量能有效隔离变量在一个程序文件中。s t a t i c i n t i;register,register变量是以寄存器(register)来存放变量,而不是一般内存。只有内部变量才能使用regi
12、ster类型变量。使用这种变量能加快变量的处理速度。但缺点是要占用CPU寄存器。如:r e g i s t e r i n t i;r e g i s t e r i n t j;变量等级的概念也同样适用于函数。若想调用不在有效范围内的函数,则要用extern扩展声明函数的有效范围。内部变量是以堆栈方式存放的,必须在函数执行时才会存在,所以称为声明(Declaration)。其它如staticauto、extern和static extern等级的变量,都是以固定的地址来存放的,而不是以堆栈方式存放的,在程序编译时就己分配了空间,所以称之为定义(Definition)o1.4.特殊字符的表示方
13、法:Table 1.1.特殊字符的表示方法符号ASCI I字符(十六进制)句柄符号作用a07BEL响铃b08BS回格focFF换页n0ALF换行r0DCR回车键t09HTtab键vOBVT空行000NUL空字符5 C反斜杠,2C单引号H22ii双引号?3F?问号1.5.格式化字符串%c,表示字符变量。%s,表示字符串变量。%f,表示浮点数变量。%d,表示整数变量。%x,表示十六进制变量。%o,表示八进制变量。1.6.指针与数组 C语言中专门用来存放内存地址的变量叫指针(pointer)变量,简称指针。&运算符用来取得变量地址,*”运算符用来取得指针变量的值。数组名就是地址变量,指向内存中存放第
14、一 个 数组元素的地址。数组元素编号从0开始,如a0表示数组a的第一个元素。数组是内存中的连续区间,可根据声明类型存放多种数值类型。如:int a10;char b20;声明一个有10个int元素的数组声明一个有2 0个char元素的数组指针示例:int*p;/*p是一个指针,p的内容是内存的地址,在这个地址中将存放一个整数。数组名和指针都是用来存放内存地址的,不过数组名具有固定长度,不可变。而指针与般变量一样,其值是可变的。1 .7.结构体结构体是用户定义的由基本数据类型组成的复合式数据类型。数组也是复合式数据类型,但二者是不同的,数组是相同类型数据的集合,而结构体是不同类型数据的集合。如我
15、们可以把一个人的姓名、性别,年龄组成个单 结构体。这样在程序处理时就把它当成个独立对象进行处理。结构体声明方法有两种,一种是分离式声明,一种是结合式声明。分离式声明是先把声明结构体,在程序中再声明结构体变量。结合式声明是把结构体声明和变量声明同时完成。分离式声明示例struct person(char name;char sex;int age;);m a i n(v o i d)s t r u c t p e r s o n w o r k e r;结合式声明示例s t r u c t p e r s o n c h a r n a m e;c h a r s e x;i n t a g e
16、;w o r k e r;每个结构体可以表示个工人的信息,如果要表示多个工人的信息,则可以用结构体数组。s t r u c t p e r s o n c h a r n a m e;c h a r s e x;i n t a g e;);m a i n(v o i d)s t r u c t p e r s o n w o r k e r 2 0 ;表示 2 0 个工人)结构体初始设置。s t r u c t p e r s o n c h a r n a m e;c h a r s e x;i n t a g e;w o r k e r=j i m s,“m a l e”,3 0 ;用”.
17、“和运算符存取结构体中的数据c 是直接存取法,”为间接存取法,用于结构体指针。如果p 是个指向person结构体的指针,则 p-name 和(*p).nam e的结果是样的。1.8.typ e d e f-自定义类型名结构体可以自定义数据类型,而 typedef可以自定义新的类型名。如:t t i n c l u de t y p e de f c h a r *S T R I N G;定义一个新的字符指针类型名S T R I N Gm a i n(v o i d)S T R I N G a;a =a b c ;p r i n t f (z/t h e a v a l u e i s%s.n
18、,a);)a为字符指针类型,自定义类型名通常以大写方式表示,以示区别。#define与typedef的区别是:#define只是单纯地进行变量替换,而typedef是创建新的类型名。typedef的个主要作用是简化声明,提高程序的可读性。如:t y p e de f s t r u c t p e r s o n c h a r n a m e;c h a r s e x;i n t a g e;P这样我们就定义一个新的结构体类型名P,在程序中我们可以使用它来声明变量。如m a i n(v o i d)p w o r k e r;w o r k e r =j i m s ,m a l e ,3
19、 0);1 .9.函数和宏函数是C代码的集合,每个C程序由个或多个函数组成,main。是个特殊的函数,是C程序的入口,每个C程序必须有且只能有一个mian()函数。ANSI函数定义:类型函数名(类型参数1,类型参数2,.)函数代码;)示例:i n t f u n c(i n t i,c h a r c)在程序中要使用我们设计开发的函数,需要先进行声明,函数声明的作用是把函数类型告诉编译器。函数声明与定义差不多,只是不包括程序主体。上面示例的函数在主程序中的声明方式如卜.:v o i d m a i n()(i n t t o t a l;i n t f u n c (i n t i,c h a
20、 r c);函数声明t o t a l =i n t (x x x,x x x);声明后才能调用该函数定义和声明中的参数类型(int,char)要相同,但名称(i,c)可以不同。当函数没有返回值时,需声定义成void类型,调用者也要做void声明。一般我们把函数的声明放在一个统一的文件中,这个文件叫头文件。在程序中用#include命令把头文件包含进来。在程序中调用函数前就不用再进行函数声明了。头文件简化了函数声明的管理并使头文件可被多个程序重复使用。大大提高C程序的开发效率。例如:我们最常使用的printf()函数,在使用前我们不需每次都进行声明操作,直接使用就可以啦。但前提是我们要把std
21、io.h头文件包含进来。printf()函数声明在stdio.h文件中已进行了声明。1 .10.A N S I标准头文件Linux系统头文件位于/usr/include中。默认情况下编译器只在该目录下搜索头文件。assert.h,定义assert宏,可用来检查程序错误。ctype.h,errno.h float.h limits.h locale.h math.h setjmp.h signal.h stdarg.h stddef.h stdio.h stdlib.h string.h time.hChapter 2.预处理C语言在程序进行编译之前,会先将程序中以“#”标记的部份进行处理。这种
22、处理叫做预处理。预处理主要的完成以卜三个内容:宏处理、头文件和条件式编译。宏处理指令语法如下:#d e f i n e 宏名字符串示例:#d e f i n e M A X 2 00宏指令语句尾不用加分号(;)宏定义可以用#undef命令取消,我们可以用该功能进行程序调试。头文件处理是把头文件中的函数声明插入程序中。条件式编译,编译器可根据条件式编译语句有选择地进代码块进行编译。选择式编译指令如卜.:#i f 表达式#i f d e f 宏名S i f n d e f 宏名t t e l s e#e n d i f如果表示式结果不为0,则编译下面的程序若宏名已被定义,则编译下面的程序若宏名未定
23、义,则编译下面的程序前面条件不成立时,则编译下面的程序结束上列各种条件式编译Chapter 3.使用GCC编译程序直接生成a.out可执行文件d e b i a n:/c#g c c h e l l o,c编译hello.c程序,生成hello可执行文件:d e b i a n:/c#g c c -o h e l l o h e l l o,c生成.s的汇编代码文件。d e b i a n r/c#g c c -S h e l l o,cChapter 4.使用g d b 调试程序如果想利用gdb工具来调试程序,在编译程序时要使用-g选项。如:d e b i a n:/c#g c c -g s
24、 e r i a l,c -o s e r i a l调试serial程序。d e b i a n:/c#g d b s e r i a lG N U g d b 6.5-d e b i a nC o p y r i g h t (C)2006 Fr e e S o f t w a r e Fo u n d a t i o n,In c.GDB i s f r e e s o f t w a r e,c o v e r e d b y t h e GN U Ge n e r a l P u b l i c L i c e n s e,a n d y o ua r ew e l c o m e
25、t o c h a n g e i t a n d/o r d i s t r i b u t e c o p i e s o f i t u n d e r c e r t a i nc o n d i t i o n s.T y p e s h o w c o p y i n g t o s e e t h e c o n d i t i o n s.T h e r e i s a b s o l u t e l y n o w a r r a n t y f o r GDB.T y p e s h o w w a r r a n t yz/f o r d e t a i l s.T h
26、i s GDB w a s c o n f i g u r e d a s z,148 6-1 i n u x-g n u,z.U s i n g h o s t l i b t h r e a d _ d bl i b r a r y /l i b/t l s/l i b t h r e a d _ d b s o.1.(g d b)l i s t8 S i n c l u d e /*错误号定义*/910 i n t m a i n(v o i d)11 12 i n t f d,n,s t a t u s,b u f f s i z e;13 s t r u c t t e r m i
27、o s a;14 s t r u c t t e r m i o s *o l d t i o;15 c h a r m 255,*c o m m;1617 f d =o p e n C/d e v/t t y S O,0_ R DW R|O _ N O CT T Y 10_ N DEL AY);(g d b)gdb的list命令是列出程序源码。下面介绍gdb下的各种操作。lis t,列出程序源代码,次只列出10行的内容.list命令可以指定范围。如:list 5,10可列出第5行到第10行的内容。ru n,执行程序。按Ctrl+c可中断程序的执行。shell,暂时退出gdb回 至ij she
28、ll环境。在shell环境用exit命令可以返回gdb。break,设置断点,后跟行号则把断点设置在指定的行号,后跟函数名则把断点设置在函数。如break 6,break function。还可根据条件设置断点,如:break 9 if result 5 0。这条命令的意思是,当运行到第9行时,如果result变量的值大于50,则中断程序。(g d b)b r e a k 6Br e a k p o i n t 1 a t 0 x 8 048 63 4:f i l e s e r i a l,c,l i n e 6.watch,指定条件,如果成立则中断。如:watch result 5 0o当
29、result的变量大于5 0时,马上中断程序。print,打印变量值,如:print resulto whatis,查看变量类型,如:whatis resulto continue,从中断点继续运行程序。s te p,从中断点开始单步运行,如果遇到函数,则进入函数单步运行。n e x t,从中断点开始单步运行,如果遇到函数,则运行函数,该命令不会进入函数单步运行,而是运行整个函数。info breakpoints,查看程序中所设置的所有中断点信息。(gdb)info breakpointsNum T ype Disp Enb Address What1 breakpoint keep y 0
30、x0 80 4863 4 in main at serial.c:6Enb字段是“y,表示断点1现正生效。disable/enable,控制中断点失效和启用。如:disable 1 o如果disable/enable命令后没有指定断点号,则该命令作用于所有已设置的断点。(gdb)disable 1(gdb)info breakpointsNum T ype Disp Enb Address What1 breakpoint keep n 0 x0 80 4863 4 in main at serial.c:6Enb字 段 由 变 成“n,断点1暂时被禁止。enable once,使断点生效次。
31、delete,删除断点。如:delete 1 o delete要指定断点号。clear,删除断点。如:clear 6o clear要指定设置断点的行号或函数名。help a ll,显示所有gdb环境的命令。在gdb环境卜,按tab键可自动补全命令。直接按回车键可重复执行上一个操作。按上下光标键可显示历史命令。Chapter 5.L in u x程序开发基础Table of Contents5.1.路径5.2.库文件5.3.预处理5.4.系统调用(system call)5.1.路径在设置Linux的系统路径时,使用冒号分隔每个路径名。如:P AT H=/z/u s r/l o c a l/s
32、b i n:/u s r/l o c a l/b i n:/u s r/s b i n:/u s r/b i n:/s b i n:/b i n:/us r/b i n/X l lz,在Linux中的程序有两种,一种是可执行程序,与Windows卜.的.exe文件类似,一种是脚本,与Windows下的.bat文件类似。Linux中常用的程序存放路径有以下几个:/b in,该路径存放系统启动时需要使用的程序。/usr/bin,该路径存放用户需使用的标准程序。/usr/local/bin,该路径存放本地安装的程序。Linux使用斜杠”/分隔路径名,而不是Windows的反斜杠”。Linux下的C编
33、译器使用GCC,由于历史的原因,在POSIX兼容的操作系统中,C编译器都叫c c,所以Linux卜也有一个cc命令,它是一个到gcc的软链接。开发工具,多数位于/usr/bin或/usr/local/bin目录下。头文件,位于/usr/include目录。头文件包含有常量定义、系统调用和库函数调用的声明。这是系统默认的头文件存放路径,在编译程序时,编译器会自动查找该目录。gcc编译器在编译程序时也可用-I参数指定另外的头文件路径。如:g c c -I/usr/loc a l/myi nc lud e te st.c。5.2.库文件库文件,库是一组已编译的函数集合,可方便我们重用代码。默认存放在
34、/lib和/usr/lib目录。库文件可分为静态和共享两类。.a,静态库文件。使用静态库将会把所有的库代码引入程序,占用更多的磁盘空间和内存空间,所以般建议使用共享库。.so,共享库文件。使用共享库的程序不包含库代码,只在程序运行才调用共享库中的代码。在编译时可用包含路径的库文件名或用-I参数指定使用的库文件,/usr/lib/libm.a等价于“m。如:g c c -o h e llo h e llo,c /usr/li b/li b m.a或用T 参数写成g c c -o h e llo h e llo,c -I m如果我们要使用的库文件不在默认位置,在编译程序时可用L参数指定库文件的路径
35、。卜面例子使用了/usr/hello/lib 目录下的 libhello 库文件:g c c -o h e llo-L/usr/h e llo/li b h e llo.c -I h e llo创建和使用静态库。分别创建两个函数,函数a 的内容如下:f ti nc lud e voi d a(c h a r*a rg)(pri ntf (f unc ti on a,h e llo world%s nz,,a rg);)函数b 的内容如下:#i nc lud e voi d b (i nt a rg)(pri ntf (f unc ti on b,h e llo world%d n,z,a rg
36、);)接着,生成两个对象文件。d e b i a n:/c#g c c -c a.c b.cd e b i a n:/c#I s*.oa.o b.o 最后,用 a r归档命令把生成的对象文件打包成个静态库libhello.a。d e b i a n:/c#a r c rv li b h e llo.a a.o b.or-a.or-b.o为我们的静态库定义一个头文件lib.h,包含这两个函数的定义。/*th i s i s a h e a d e r f i le.*/voi d a(c h a r*a rg);voi d b(i nt a rg);*创建ji ms.c程序,内容如下。#!c p
37、lusplus#i nc lud ei nt ma i n()(a(/zji ms.ya ng);b(3);e xi t(0);利用静态链接库编译程序。d e b i a n:/c#g c c -c ji ms.cd e b i a n:/c#g c c -o ji ms ji ms.o li b h e llo.ad e b i a n/c#./ji msf unc ti on a,h e llo world ji ms.ya ngf unc ti on b,h e llo world 3d e b i a nr/c#gcc-o jims jims.o libhello.a 也可以写成gcc
38、-o jims jims.o-L.-IhellOo共享库比静态库具有以下的优点:当多个进程使用同一共享库时,Linux会把共享库中存放可执行代码的内存进行共享。所以共享库可节省内存,提高系统性能。程序可共享代码,减少磁盘空间占用。共享库出错,只要重新编译共享库即可,不用重新编译应用程序。Idconfig程序用来安装个共享库,。只有在为系统库安装一个库的时候,才需要在/etc/ld.so.conf中创建记录,并运行Idconfig更新共享库的缓存。LD_LIBRARY_PATH环境变量用来指定附加的库文件路径。系统默认的库文件路径位于/usr/lib和/lib目 录下。LD_PRELOAD环境变
39、量指定提前载入的库,用于替代系统库。5.3.预处理预处理,在程序开头以“#开头的命令就是预处理命令,它在语法扫描和分析法时被预处理程序处理。预处理有以下几类:宏定义,用#define指令定义。如:#define BUFFER 1024取消宏定义用#undef指令。宏还可带参数,如:t t d e f i n e B U F(x)x*3包含头文件,用#include指令,可把包含的文件代码插入当前位置。如:(i n c l u d e o包含的文件可以用尖括号,也可用双引号,如:#i n c l u d e s t d i o.h。不同之处是,使用尖括号表示在系统的包含目录(/usr/inclu
40、de)下查找该文件,而双引号表示在当前目录下查找包含文件。每行只能包含个包含文件,要包含多个文件要用多个#include 指令。条件编译,格式如下:格式一,如果定义了标识符,则编译程序段1,否则编译程序段2:#i f d e f标识符程序段1#e l s e程序段2#e n d i f格式二,如果定义了标识符,则编译程序段2,否则编译程序段L与格式一相反:t t i f n d e f标识符程序段1#e l s e程序段2#e n d i f格式三,常量表达式为真则编译程序段L否则编译程序段2:#i f常量表达式程序段1#e l s e程序段2#e n d i f使用gcc编译程序时,要经过四
41、个步骤。预处理(Pre-Processing),用-E参数可以生成预处理后的文件。d e b i a n:/c#g c c -E h e l l o.c o h e l l o,i 编 译(Compiling)汇 编(Assembling)链 接(Linking)GCC默认将.i文件看成是预处理后的C语言源代码,所以我们可以这样把.i文件编译成目标文件。d e b i a n:“#g c c -c h e l l o,i -o h e l l o.o 在GCC中使用-pedantic选项能够帮助程序员发现一些不符合ANSI/ISO C标准的代码,但不是全部。从程序员的角度看,函数库实际上就是些
42、头文件(.h)和库文件(.so或者.a)的集合。5.4.系统调用(system ca ll)要理解系统调用就要先理解程序代码运行的两种模式,一种是用户模式,一种是内核模式。我们编写的应用程序运行在用户模式下,而设备驱动程序和文件系统运行在内核模式。在用户模式下运行的程序受到严格的管理,不会破坏系统级应用。而在内核模式下运行的程序可以对电脑有完全的访问权。系统调用就是运行在内核模式下的代码为运行在用户模式下的代码提供服务。系统调用的错误返回码是负数,定义在errno.h(文件中。在系统调用中发生错误,C函数库就会用错误码填充全局变量errno用perror()和strerror。函数可以输出错误
43、信息。系统调用多数在unistd.hv中定义。Chapter 6.文件处理在Linux系统内所有东西都是以文件的形式来表示的,除一般的磁盘文件外,还有设备文件,如硬盘、声卡、串口、打印机等。设备文件又可分为字符设备文件(character devices)和块设备文件(blockdevices),使用man hier命令可以查看Linux文件系统的分层结构。文件的处理方法一般有五种,分别是:open,打开一个文件或设备。close,关闭一个打开的文件或设备。read,从一个打开的文件或者设备中读取信息。w rite,写入一个文件或设备。ioctl,把控制信息传递给设备驱动程序。open,clo
44、se,read,w rite和ioctl都是低级的,没有缓冲的文件操作函数,在实际程序开发中较少使用,般我们使用标准I/O函数库来处理文件操作。如:fopen,fclose,tread,fwrite,fflush等。在使用标准I/O库时,需用到stdio.h头文件。fopen()这个标准I/O库函数用于打开文件,在Linux中文件要先打开后才能进行读写操作。S i nc l ud e F I L E *f ope n(c onst c h a r*f i l e na m e,c onst c h a r*m od e);*m od e 选项:r或orb 为读打开文件 w 或 wb b 为写打
45、开文件,如果文件不存在则创建,如果存在则覆盖 a 或 a b b 为追加内容而打开文件“r+或 o rb+或 r+b r为更新打开文件,不会覆盖旧文件w+或wb+b或 w+b w为更新打开文件,会覆盖旧文件 a+a或“a b+或“a+b 为更新打开文件,更新内容追加到文件末尾一些常用的文件和目录维护函数:chmod、chown unlink、link symlink mkdir、rmdir chdirgetcwd opendir,closedir、readdir、telldir、seekdir 等。fcntl用于维护文件描述符,mmap用于分享内存。创建文档并输入信息的示例代码:tti nc
46、l ud e m a i n(voi d)F I L E *f pl;c h a r c;f pl =f ope n(te xt.txt,w);wh i l e (c =g e tc h a r()!=n)putc (c,f pl);f c l ose(f pl);)显示路径的示例代码S i nc l ud e tti nc l ud e W i nc l ud e S i nc l ud e S i nc l ud e S i nc l ud e i nt m a i n(i nt a rg c,c h a r*a rg v )(c h a r*topd i r=.;i f (a rg c
47、=2)topd i r=a rg vL l ;pri ntf(D i re c tory sc a n of%s n,topd i r);pri ntd i r(topd i r,0);pri ntf (z,d one.n);e xi t(0);pri ntd i r(c h a r*d i r,i nt d e pth)D I R *d p;struc t d i re nt G e ntry;struc t sta t sta tb uf;i f(d p=ope nd i r(d i r)=N U L L)f pri ntf (std e rr,z,c a nnot ope n d i r
48、e c tory:%s n,z,d i r);re turn;)c h d i r(d i r);wh i l e (e ntry=re a d d i r(d p)!=N U L L)I sta t(e ntry-d _ na m e,&sta tb uf);i f(S I S D I R(sta tb uf.st_ m od e)i f (strc m p(,,.,z,e ntry-d _ na m e)=0|strc m p(zz.,z,e ntry-d _ na m e)=0)c onti nue;pri ntf(%*s%s/n,d e pth,,e ntry-d _ na m e);
49、pri ntd i r(e ntry-d _ na m e,d e pth+4);)e l se pri ntf (,%*s%s n/,,d e pth,,e ntry-d _ na m e);c h d i r();c l ose d i r(d p);Chapter 7.Linux 环境编程Table of Contents7.1.参数选项7.2.环境变量7.3.时间7.4.临时文件7.5.用户信息7 6.日志信息7.1.参数选项void main。表示程序没有参数,int main(int argc,char*argv表示程序要带参数,argc保存着参数的个数,argv口数组保存着参数列
50、表。如:d e b i a n:#m yte st a b ca rg c:4t m yt.e st,,a,b,c iJgetopt()函数和getoptong()用来处理程序选项getoptong()函 数 可 以 处 理 以 开头的选项。Gnu官方手册页:http:www.gnu.org/software/libc/manual/html node/Getopt.htmI获取命令行参数的示例代码:S i nc l ud e tti nc l ud e i nt m a i n(i nt a rg c,c h a r*a rg v 口)(i nt opt;wh i l e (opt=g e