linux下的C编程.pdf
《linux下的C编程.pdf》由会员分享,可在线阅读,更多相关《linux下的C编程.pdf(78页珍藏版)》请在淘文阁 - 分享文档赚钱的网站上搜索。
1、 第一篇:起步篇第一篇:起步篇 千里之行,始于足下。第一章第一章 UNIX初步初步 UNIX自 1969 年诞生以来,已经发展为 System III&V、BSD 和 Linux 三大分支。UniX通过 shell 与用户交互,它是用户与系统间的界面。使用好 shell 对于学习使用 UNIX来说是必须的。不需要你记住所有的命令,但基础的文件操作、目录操作及系统命令等却是必须的。Vi 对于初学者是难点,不过只要通过一段时间的练习就能习惯;而且你会很快发现,它功能强大、更加灵活。这里不多说了:)第二章第二章 编程套件编程套件 学习 UNIX 对于初学者有几种选择。一种就是最直接的,在本机上安装
2、UNIX系统,不如说 Linux 分支中的 Red Hat等;一种是在 Windows环境下使用虚拟机方式安装 UNIX 系统;另一种则是使用网络终端登录到网络环境中的某个 UNIX系统中。如果你相对黑洞洞的 UNIX字符界面更喜欢舒适美观的 Windows界面,那么推荐你选择第三种方式。开发套件包括:编辑器 UltraEdit、网络终端 SecureCRT 或其他。编译器就不用说了,自然是 cc(gcc或 xlc 系列)。这是 C 语言开发必不可少的。其中要注意-I(加载头文件路径)、-L(加载库文件路径)及-D(宏定义)参数的使用。Make 工具使用。如何编写 makefile是关键。后面
3、项目中使用时会详细介绍。Gdb 调试器。Gdb 乃符号级调试工具,它控制程序的内部执行,利用断点设置、单步运行等手段,将程序的执行过程逐步展示在调试者目前。这种调试方式在短代码中可以发挥得很好。事实上,随着软件项目的扩大化、复杂化和分布化,很少有程序员直接通过 Gdb 等工具调试;使用日志记录调试方法比Gdb 等调试工具更为便捷和广泛。C 工具:lint检查源代码是否正确,gprof分析程序时间消费量,cflow生成 C 语言流程图。第三章第三章 库的使用库的使用 库分静态库和动态库两种。静态库的操作工具:ar命令。编写及使用静态库编写及使用静态库(1)设计库源码 pr1.c和 pr2.c r
4、ootbillstone make_lib#cat pr1.c void print1()printf(This is the first lib src!n);rootbillstone make_lib#cat pr2.c void print2()printf(This is the second src lib!n);(2)编译.c 文件 billbillstone make_lib$cc-O-c pr1.c pr2.c billbillstone make_lib$ls-l pr*.o-rw-rw-r-1 bill bill 804 4月 15 11:11 pr1.o-rw-rw-r
5、-1 bill bill 804 4月 15 11:11 pr2.o(3)链接静态库 为了在编译程序中正确找到库文件,静态库必须按照 libname.a 的规则命名,如下例中name=pr.billbillstone make_lib$ar-rsv libpr.a pr1.o pr2.o a-pr1.o a-pr2.o billbillstone make_lib$ls-l*.a-rw-rw-r-1 bill bill 1822 4月 15 11:12 libpr.a billbillstone make_lib$ar-t libpr.a pr1.o pr2.o(4)调用库函数代码 main.
6、c billbillstone make_lib$cat main.c int main()print1();print2();return 0;(5)编译链接选项 -L 及-l 参数放在后面.其中,-L 加载库文件路径,-l 指明库文件名字.billbillstone make_lib$gcc-o main main.c-L./-lpr billbillstone make_lib$ls-l main*-rwxrwxr-x 1 bill bill 11805 4 月 15 11:17 main-rw-rw-r-1 bill bill 50 4月 15 11:15 main.c (6)执行目标
7、程序 billbillstone make_lib$./main This is the first lib src!This is the second src lib!billbillstone make_lib$编写动态库编写动态库(1)设计库代码 billbillstone make_lib$cat pr1.c int p=2;void print()printf(This is the first dll src!n);billbillstone make_lib$(2)生成动态库 billbillstone make_lib$gcc-O-fpic-shared-o dl.so pr
8、1.c billbillstone make_lib$ls-l*.so-rwxrwxr-x 1 bill bill 6592 4月 15 15:19 dl.so billbillstone make_lib$动态库的隐式调用动态库的隐式调用 在编译调用库函数代码时指明动态库的位置及名字,看下面实例 billbillstone make_lib$cat main.c int main()print();return 0;billbillstone make_lib$gcc-o tdl main.c./dl.so billbillstone make_lib$./tdl This is the f
9、irst dll src!billbillstone make_lib$当动态库的位置活名字发生改变时,程序将无法正常运行;而动态库取代静态库的好处之一则是通过更新动态库而随时升级库的内容.动态库的显式调用动态库的显式调用 显式调用动态库需要四个函数的支持,函数 dlopen 打开动态库,函数 dlsym获取动态库中对象基址,函数 dlerror获取显式动态库操作中的错误信息,函数 doclose 关闭动态库.billbillstone make_lib$cat main.c#include int main()void*pHandle;void(*pFunc)();/指向函数的指针 int*
10、p;pHandle=dlopen(./d1.so,RTLD_NOW);/打开动态库 if(!pHandle)printf(Cant find d1.so n);exit(1);pFunc=(void(*)()dlsym(pHandle,print);/获取库函数 print 的地址 if(pFunc)pFunc();else printf(Cant find function printn);p=(int*)dlsym(pHandle,p);/获取库变量 p的地址 if(p)printf(p=%dn,*p);else printf(Cant find int pn);dlclose(pHand
11、le);/关闭动态库 return 0;billbillstone make_lib$gcc-o tds main.c-ldl billbillstone make_lib$./tds This is the first dll src!p=2 billbillstone make_lib$上面的程序 tds显式调用了共享库 d1.so 中的函数 print 和变量 p.第二篇:文件子系统 普天之下,莫非王土;率土之滨,莫非王臣.UNIX 之中,莫非文件.第四章第四章 文件系统结构文件系统结构 磁盘在使用前,需要分区和格式化.格式化操作将在磁盘分区中创建文件系统,它们将确定文件的存储方式和索引
12、方法,确定磁盘空间分配和回收算法.UNIX文件系统的存储由三级构成,其中目录存储了文件的层次结构,数据块存储了文件的具体信息,i 节点是连接文件层次结构与其数据内容的桥梁.UNIX文件系统将磁盘空间划分为一系列大小相同的块,划分为引导块,超级块,i 节点区和数据区四个部分.文件系统通过 i 节点对文件进行控制和管理.其中,每个文件对应一个 i 节点,每个 i 节点具有唯一的节点号,记录了文件的属性和内容在磁盘上的存储位置.但文件名并不记录在 i 节点里,而是存储在目录文件中.磁盘文件如何存储磁盘文件如何存储?文件系统通过目录记载文件名及其对应的 i 节点编号,通过 i节点记录文件的信息和内容.
13、事实上,i 节点直接记录的只是文件的属性,文件的具体内容存储在数据区的数据块中,i 节点中仅保留了一个来记录文件内容存储的位置.由 13 个块号组成,每个块号占用 4 个字节,代表了数据区中的一个数据块编号.UNIX文件系统采用三级索引结构存储文件,它把分为直接索引地址,一级索引地址,二级索引地址和三级索引地址等四个部分.其中前 10 项为直接索引地址,直接指向文件数据所在磁盘快的块号.第11/12/13 项分别为一级/二级/三级索引地址.一级间接索引的含义在于其存储的并非文件数据所在磁盘块的块号,而是先指向一个然后再指向具体磁盘块的块号.同理,二级/三级间接索引则是先间接指向了两次才指向具体
14、磁盘快的块号.如果文件系统的数据块大小为 1kB,每个能够记录 256 个数据项.那么,直接索引能管辖10 个数据块,而一级索引能管辖 1*256 个数据块,二级索引能管辖 1*256*256(65536)个数据块,三级索引能管辖 1*256*256*256(16777216)个数据块.例题:大小为 56000K的文件,占用多少索引块空间?答:因为(10+256)56000 tm_year+1900,mtime-tm_mon+1,mtime-tm_mday);设计类似于 UNIX命令的程序 lsl,主程序如下 billbillstone Unix_study$cat lsl.c#include
15、#include#include#include int GetFileType(mode_t st_mode,char*resp);int GetFileMode(mode_t st_mode,char*resp);int GetFileOtherAttr(struct stat info,char*resp);int main(int argc,char*argv)struct stat info;char buf100,*p=buf;if(argc!=2)printf(Usage:lsl filenamen);return;memset(buf,0,sizeof(buf);if(lsta
16、t(argv1,&info)=0)p+=GetFileType(info.st_mode,p);p+=GetFileMode(info.st_mode,p);p+=GetFileOtherAttr(info,p);printf(%s%sn,buf,argv1);else printf(Open file failed!n);return 0;运行结果如下:billbillstone Unix_study$make lsl cc lsl.c -o lsl billbillstone Unix_study$./lsl Usage:lsl filename billbillstone Unix_st
17、udy$./lsl/etc/passwd-rw-r-r-1 0 0 1639 20090328/etc/passwd billbillstone Unix_study$ls-l/etc/passwd-rw-r-r-1 root root 1639 3月 28 16:38/etc/passwd 第五章第五章 标准文件编程库标准文件编程库 在 UNIX的应用中,读写文件是最常见的任务.标准文件编程库就是操作文件最简单的工具.标准编程函数库对文件流的输入输出操作非常灵活,我们既可以采用所见即所得的方式,以无格式方式读写文件,又可以对输入输出数据进行转化,以有格式方式读写文件.文件的无格式读写文件的无
18、格式读写 无格式读写分三类:按字符读写,按行读写和按块读写.字符读写函数族:#include int getc(FILE*stream);int fgetc(FILE*stream);int putc(int c,FILE*stream);int fputc(int c,FILE*stream);函数 fgetc的功能类似于 getc,不同的是,它的执行速度远低于 getc.行读写函数族:#include char*gets(char*s);char*fgets(char*s,int n,FILE*stream);int puts(const char*s);int fputs(const c
19、har*s,FILE*stream);函数 fgets中加入了放溢出控制,应该优先选用.注意函数 fputs把字符串 s(不包括结束符0)写入文件流 stream中,但不在输出换行符n;而函数 puts 则自动输出换行符.块读写函数族:#include size_t fread(void*ptr,size_t size,size_t nitems,FILE*stream);size_t fwrite(const void*ptr,size_t size,size_t nitems,FILE*stream);函数 fread和 fwrite 都不返回实际读写的字符个数,而返回的是实际读写的数据项
20、数.块读写函数常用于保存和恢复内存数据.文件的格式化读写文件的格式化读写 文件格式化读写时能够自动转换的数据格式有:数据类型,精度,宽度,进制和标志等,而其一般格式为%标志 宽度.精度 类型 格式化输出函数族#include int printf(const char*format,/*arg,*/.);int fprintf(FILE*stream,const char*format,/*arg,*/.);int sprintf(char*s,const char*format,/*arg,*/.);在做字符串处理时应该善用 sprintf函数.格式化输入函数族#include int sc
21、anf(const char format,/*pointer,*/.);int fscanf(FILE*stream,const char format,/*pointer,*/.);int sscanf(const char*s,const char format,/*pointer,*/.);二进制读写与文本读写二进制读写与文本读写 记得刚开始学习 C 语言的文件操作时,这是一个最让我疑惑的问题.我们都知道在调用 fopen 函数时需要指定操作类型,比如说文本写r和二进制写rb.那么它们究竟有何区别呢?这要牵涉到两种存储方式:以字符为单位存储的文本文件和以二进制数据为单位存储的二进制文件
22、.举个例子:我们通常阅读的 Readme.txt文件就是文本文件,该类型文件存储的是一个一个的字符,这些字符往往是可以打印的;而我们的可执行程序(比如 a.out)则是二进制文件,该文件是不可读的,需要解析才能识别.那么在调用 fopen 函数时该如何选择呢?如果你是先写入再从另外的地方读出,那么两种方式都可以;只要按写入时的方式读取就可以了.但是,比起文本方式,二进制方式在保存信息时有着优势:a)加快了程序的执行速度,提高了软件的执行效率.内存中存储的都是二进制信息,直接以二进制方式与文件交互,可以免除二进制格式与文本格式之间的信息转换过程.b)节省了存储空间.一般来讲,二进制信息比文件信息
23、占用更少的空间,比如 8 位的整型数采用文本方式存储至少需要 8 字节,而采用二进制存储只需一个整型即 4 个字节.编写变长参数函数编写变长参数函数 文件的格式化输入输出函数都支持变长参数.定义时,变长参数列表通过省略号.表示,因此函数定义格式为:type 函数名(参数 1,参数 2,参数 n,.);UNIX的变长参数通过 va_list 对象实现,定义在文件stdarg.h中,变长参数的应用模板如下所示:#include function(parmN,.)va_list pvar;.va_start(pvar,parmN);while().f=va_arg(pvar,type);.va_en
24、d(pvar);va_list 数据类型变量 pvar访问变长参数列表中的参数.宏 va_start 初始化变长参数列表,根据 parmN判断参数列表的起始位置.va_arg 获取变长列表中参数的值,type指示参数的类型,也使宏 va_arg 返回数值的类型.宏 va_arg 执行完毕后自动更新对象 pvar,将其指向下一个参数.va_end 关闭对变长参数的访问.下面给出一个实例 mysum,计算输入参数的和并返回 billbillstone Unix_study$cat mysum.c#include int mysum(int i,.)/参数列表中,第一个参数指示累加数的个数 int
25、r=0,j=0;va_list pvar;va_start(pvar,i);for(j=0;ji;j+)r+=va_arg(pvar,int);va_end(pvar);return(r);int main()printf(sum(1,4)=%dn,mysum(1,4);printf(sum(2,4,8)=%dn,mysum(2,4,8);return 0;billbillstone Unix_study$make mysum cc mysum.c -o mysum billbillstone Unix_study$./mysum sum(1,4)=4 sum(2,4,8)=12 billbi
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- linux 编程
限制150内