学习《精通UNIX下C语言编程及项目实践》

整理文档很辛苦,赏杯茶钱您下走!

免费阅读已结束,点击下载阅读编辑剩下 ...

阅读已结束,您可以下载文档离线阅读编辑

资源描述

学习《精通UNIX下C语言编程及项目实践》1.第一篇:起步篇千里之行,始于足下。一、UNIX初步UNIX自1969年诞生以来,已经发展为SystemIII&V、BSD和Linux三大分支。UniX通过shell与用户交互,它是用户与系统间的界面。使用好shell对于学习使用UNIX来说是必须的。不需要你记住所有的命令,但基础的文件操作、目录操作及系统命令等却是必须的。Vi对于初学者是难点,不过只要通过一段时间的练习就能习惯;而且你会很快发现,它功能强大、更加灵活。这里不多说了:)二、编程套件学习UNIX对于初学者有几种选择。一种就是最直接的,在本机上安装UNIX系统,不如说Linux分支中的RedHat等;一种是在Windows环境下使用虚拟机方式安装UNIX系统;另一种则是使用网络终端登录到网络环境中的某个UNIX系统中。如果你相对黑洞洞的UNIX字符界面更喜欢舒适美观的Windows界面,那么推荐你选择第三种方式。开发套件包括:编辑器UltraEdit、网络终端SecureCRT或其他。编译器就不用说了,自然是cc(gcc或xlc系列)。这是C语言开发必不可少的。其中要注意-I(加载头文件路径)、-L(加载库文件路径)及-D(宏定义)参数的使用。Make工具使用。如何编写makefile是关键。后面项目中使用时会详细介绍。Gdb调试器。Gdb乃符号级调试工具,它控制程序的内部执行,利用断点设置、单步运行等手段,将程序的执行过程逐步展示在调试者目前。这种调试方式在短代码中可以发挥得很好。事实上,随着软件项目的扩大化、复杂化和分布化,很少有程序员直接通过Gdb等工具调试;使用日志记录调试方法比Gdb等调试工具更为便捷和广泛。C工具:lint检查源代码是否正确,gprof分析程序时间消费量,cflow生成C语言流程图。三、库的使用库分静态库和动态库两种。静态库的操作工具:ar命令。编写及使用静态库:(1)设计库源码pr1.c和pr2.c[root@billstonemake_lib]#catpr1.cvoidprint1(){printf(Thisisthefirstlibsrc!\n);}[root@billstonemake_lib]#catpr2.cvoidprint2(){printf(Thisisthesecondsrclib!\n);}(2)编译.c文件[bill@billstonemake_lib]$cc-O-cpr1.cpr2.c[bill@billstonemake_lib]$ls-lpr*.o-rw-rw-r--1billbill8044月1511:11pr1.o-rw-rw-r--1billbill8044月1511:11pr2.o(3)链接静态库为了在编译程序中正确找到库文件,静态库必须按照lib[name].a的规则命名,如下例中[name]=pr.[bill@billstonemake_lib]$ar-rsvlibpr.apr1.opr2.oa-pr1.oa-pr2.o[bill@billstonemake_lib]$ls-l*.a-rw-rw-r--1billbill18224月1511:12libpr.a[bill@billstonemake_lib]$ar-tlibpr.apr1.opr2.o(4)调用库函数代码main.c[bill@billstonemake_lib]$catmain.cintmain(){print1();print2();return0;}(5)编译链接选项-L及-l参数放在后面.其中,-L加载库文件路径,-l指明库文件名字.[bill@billstonemake_lib]$gcc-omainmain.c-L./-lpr[bill@billstonemake_lib]$ls-lmain*-rwxrwxr-x1billbill118054月1511:17main-rw-rw-r--1billbill504月1511:15main.c(6)执行目标程序[bill@billstonemake_lib]$./mainThisisthefirstlibsrc!Thisisthesecondsrclib![bill@billstonemake_lib]$编写动态库:(1)设计库代码[bill@billstonemake_lib]$catpr1.cintp=2;voidprint(){printf(Thisisthefirstdllsrc!\n);}[bill@billstonemake_lib]$(2)生成动态库[bill@billstonemake_lib]$gcc-O-fpic-shared-odl.sopr1.c[bill@billstonemake_lib]$ls-l*.so-rwxrwxr-x1billbill65924月1515:19dl.so[bill@billstonemake_lib]$动态库的隐式调用:在编译调用库函数代码时指明动态库的位置及名字,看下面实例[bill@billstonemake_lib]$catmain.cintmain(){print();return0;}[bill@billstonemake_lib]$gcc-otdlmain.c./dl.so[bill@billstonemake_lib]$./tdlThisisthefirstdllsrc![bill@billstonemake_lib]$当动态库的位置活名字发生改变时,程序将无法正常运行;而动态库取代静态库的好处之一则是通过更新动态库而随时升级库的内容.动态库的显式调用:显式调用动态库需要四个函数的支持,函数dlopen打开动态库,函数dlsym获取动态库中对象基址,函数dlerror获取显式动态库操作中的错误信息,函数doclose关闭动态库.[bill@billstonemake_lib]$catmain.c#includedlfcn.hintmain(){void*pHandle;void(*pFunc)();//指向函数的指针int*p;pHandle=dlopen(./d1.so,RTLD_NOW);//打开动态库if(!pHandle){printf(Can'tfindd1.so\n);exit(1);}pFunc=(void(*)())dlsym(pHandle,print);//获取库函数print的地址if(pFunc)pFunc();elseprintf(Can'tfindfunctionprint\n);p=(int*)dlsym(pHandle,p);//获取库变量p的地址if(p)printf(p=%d\n,*p);elseprintf(Can'tfindintp\n);dlclose(pHandle);//关闭动态库return0;}[bill@billstonemake_lib]$gcc-otdsmain.c-ldl[bill@billstonemake_lib]$./tdsThisisthefirstdllsrc!p=2[bill@billstonemake_lib]$上面的程序tds显式调用了共享库d1.so中的函数print和变量p.第二篇:文件子系统普天之下,莫非王土;率土之滨,莫非王臣.UNIX之中,莫非文件.四、文件系统结构磁盘在使用前,需要分区和格式化.格式化操作将在磁盘分区中创建文件系统,它们将确定文件的存储方式和索引方法,确定磁盘空间分配和回收算法.UNIX文件系统的存储由目录-i节点-数据块三级构成,其中目录存储了文件的层次结构,数据块存储了文件的具体信息,i节点是连接文件层次结构与其数据内容的桥梁.UNIX文件系统将磁盘空间划分为一系列大小相同的块,划分为引导块、超级块、i节点区和数据区四个部分.文件系统通过i节点对文件进行控制和管理.其中,每个文件对应一个i节点,每个i节点具有唯一的节点号,记录了文件的属性和内容在磁盘上的存储位置.但文件名并不记录在i节点里,而是存储在目录文件中.磁盘文件如何存储?文件系统通过目录记载文件名及其对应的i节点编号,通过i节点记录文件的信息和内容.事实上,i节点直接记录的只是文件的属性,文件的具体内容存储在数据区的数据块中,i节点中仅保留了一个磁盘地址表来记录文件内容存储的位置.磁盘文件表由13个块号组成,每个块号占用4个字节,代表了数据区中的一个数据块编号.UNIX文件系统采用三级索引结构存储文件,它把磁盘地址表分为直接索引地址,一级索引地址,二级索引地址和三级索引地址等四个部分.其中前10项为直接索引地址,直接指向文件数据所在磁盘快的块号.第11/12/13项分别为一级/二级/三级索引地址.一级间接索引的含义在于其存储的并非文件数据所在磁盘块的块号,而是先指向一个磁盘块号表然后再指向具体磁盘块的块号.同理,二级/三级间接索引则是先间接指向了两次磁盘块号表才指向具体磁盘块的块号.如果文件系统的数据块大小为1kB,每个磁盘块号表能够记录256个数据项.那么,直接索引能管辖10个数据块,而一级索引能管辖1*256个数据块,二级索引能管辖1*256*256(65536)个数据块,三级索引能管辖1*256*256*256(16777216)个数据块.例题:大小为56000K的文件,占用多少索引块空间?答:因为(10+256)56000(10+256+65536),故该文件具有二级间接索引.(56000-10-256)/256=217.7,则文件需要二级间接索引块为218个,所以总索引块需要1(一级间接索引块)+1(二级间接索引块)+218=220.磁盘文件读取示例(仿ls命令)通过stat结构中st_mode判断文件类型intGetFileType(mode_tst_mode,char*resp){if(resp==NULL)return0;if(S_ISDIR(st_mode))resp[0]='d';//使用宏定义判断elseif(S_ISCHR(st_mode))resp[0]='c';elseif(S_ISBLK(st_mode))resp[0]='b';elseif(S_ISREG(st_mode))resp[0]='-';elseif(S_ISFIFO(st_mode))resp[0]='p';elseif(S_ISLNK(st_mode))resp[0]='l';elseresp[0]='';return1;}同样,通过st_mode判断文件访问权限intGetFileMode(mode_tst_mode,char*resp){if(resp==NULL)return0;memset(resp,'-',9);if(st_mode&S_IRUSR)resp[0]='r';//使用各种宏定义与st_mode做与处理判断if(st_mode&S_IWUSR)resp[1]='w';if(st_mode&S_IXUSR)resp[2]='x';if(st_mode&S_IRGRP)resp[3]='r';if(st_mode&S_IWGRP)resp[4]='w';if(st_mode&S_IXGRP)resp[5]='x';if(st_mode&S_IROTH)resp[6]='r';if(st_mode&S_IWOTH)resp[7]='w';if(st_mode&S_IXOTH)resp[8]='x';return9;}处理文件其他属性如下intGetFileOtherAttr(structstatinfo,char*resp){structtm*mtime;if(resp==NULL)return0;mtime=localtime(&info.st_mtime);//按ls命令显示顺序处理其他属性return(sprintf(resp,%3d%6d%6d%11d%04d%02d%02d,info.st_nlink,info.st_uid,\i

1 / 28
下载文档,编辑使用

©2015-2020 m.777doc.com 三七文档.

备案号:鲁ICP备2024069028号-1 客服联系 QQ:2149211541

×
保存成功