您好,欢迎访问三七文档
当前位置:首页 > 行业资料 > 酒店餐饮 > 第五章 Linux系统接口
上章回顾Linux的文件模型,进程模型,与GNU程序更好的原因参数和选项,描述了命令行参数的解析技术系统的环境变量添加,删除,引用的方法如何创建共享库,使用共享库,以及共享库的工作原理Linux系统接口第5章本章目标理解Linux中文件描述符的概念,以及一切皆是文件的思想。熟练运用Linux提供的文件IO操作函数通过实例了解标准C库是通过系统调用来实现的掌握Linux中可执行程序的地址空间,以及malloc库函数的一种简单实现。本章结构Linux系统接口Unix/Linux地址空间文件IOAPI理解文件描述符内存管理实例:fopen与getc的实现隐含内存分配函数实例实例:存储分配程序其他常用API低级IO—read.writeOpen/close与creat/unlink随机访问--lseek实例:目录列表1-1理解Linux文件描述符“一切皆是文件”输入输出设备被看成文件输入输出通过读写文件完成读写文件之前做什么打开文件打开文件获得什么?Shell默认打开三个文件标准输入:0标准输出:1标准错误:2标准输入输出重定向你能确定输入从哪来?输出那里去?文件描述符1.系统打开文件成功时返回的小的非负整数2.用户程序通过文件描述符引用文件2-1低级IO—read,write#includeunistd.hssize_tread(intfd,char*buf,size_tn);ssize_twrite(intfd,char*buf,size_tn);代表文件的文件描述符ssize_t与size_t的区别?前者是带符号的整型,后者是无符号整型2-1低级IO—read,write#includeunistd.h#includestdio.hintmain(){charbuf[BUFSIZ];intn;while((n=read(0,buf,BUFSIZ))0)write(1,buf,n);return0;}标准输入标准输出这个程序作用是什么BUFSIZ的大小因系统各异,定义于stdio.h中2-1低级IO—read,write#includestdio.h#includeunistd.hintgetchar(void){charc;return(read(0,&c,1)==1)?\(unsignedchar)c:EOF;}!Getchar函数返回的并不是char类型,而是int类型在多数系统中的值为-1,所以决定了getchar的返回值是int2-1低级IO—read,write带有缓冲的版本#includestdio.h#includeunistd.h#undefgetcharintgetchar(void){staticcharbuf[BUFSIZ];staticchar*bufp=buf;staticintn=0;if(n==0){/*缓冲区为空*/n=read(0,buf,sizeofbuf);bufp=buf;}return(--n=0)?(unsignedchar)*bufp++:EOF;}从标准输入一次读取sizeofbuf个字符至缓冲区从缓冲区中返回一个字符只有当缓冲区为空的时候,才从标准输入去读因为在stdio.h中定义了getchar这个宏,在这里重定义,所以需要undef2-2open/close与creat/unlink#includefcntl.h#includesys/types.h#includesys/stat.hintopen(char*name,intflags);或intopen(char*name,intflags,mode_tmode);成功返回文件描述符(非负数),失败返回负数。O_RDONLYO_WRONLYO_RDWD….….指明文件的权限2-2open/close与creat/unlink#includefcntl.h#includesys/types.h#includesys/stat.hintcreat(char*name,mode_tmode);成功返回文件描述符(非负数),失败返回负数。指明文件的权限open()函数的flag|O_CREAT也可以用创建新文件2-2open/close与creat/unlink简化的cp程序if((f1=open(argv[1],O_RDONLY,0))==-1)error(cp:can'topen%s,argv[1]);if((f2=creat(argv[2],O_RDWR))==-1)error(cp:can'tcreate%s,mode%03o,argv[2],O_RDWR);while((n=read(f1,buf,BUFSIZ))0)if(write(f2,buf,n)!=n)error(cp:writeerroronfile%s,argv[2]);打开文件1和文件2从f1读取BUFSIZ个字符到缓冲区把读取缓冲区中的数据写入到文件22-2open/close与creat/unlink#includeunistd.hintclose(intfd);intunlink(constchar*pathname);用open或creat函数返回的文件描述作为参数,意为关闭,之后文件描述符不可再用注意此函数以文件路径名为参数,和remove库函数意义相同成功返回0,失败返回-1,高质量的编程应该检查返回值。2-3随机访问-lseek….….….….读文件写文件read两个字节后,文件的位置在哪?Read是指针自动向后移动write两个字节后,文件的位置在哪?Write也是指针自动向后移动如果我想随机的移动怎么办?2-3随机访问-lseek在文件中任意移动位置、而不读写数据。#includesys/types.h#includeunistd.hoff_tlseek(intfd,off_toffset,intwhence);取值为:SEEK_SETSEEK_CURSEEK_END相对于whence的偏移量返回相对于文件开始位置的偏移量2-3随机访问-lseek#includeunistd.h#includesys/types.h/*get:从pos位置处读取n个字节*/intget(intfd,longpos,char*buf,intn){if(lseek(fd,pos,0)=0)returnread(fd,buf,n);elsereturn-1;}需要确保操作成功,这是常见的编程失误2-4其他的常用文件IOAPI#includestdio.hintfileno(FILE*stream);在文件指针和文件描述符之间建立对应关系#includesys/types.h#includesys/stat.h#includeunistd.hintmkdir(constchar*pathname,mode_tmode);intrmdir(constchar*pathname);创建和删除目录。2-4其他的常用文件IOAPI#includesys/types.h#includedirent.hDIR*opendir(constchar*name);structdirent*readdir(DIR*dir);intclosedir(DIR*dir);voidrewinddir(DIR*dirp);打开目录。读取目录,返回一个dirent结构关闭打开的目录返回到目录的头部#includesys/types.h#includesys/stat.h#includeunistd.hintstat(constchar*filename,structstat*buf);读取文件的信息。2-5,2-6实验用IO系统调用对标准库函数的简单实现阶段总结Linux的IO调用是通过文件描述符来操作文件的open,creat,read,write,unlink,lseek系统调用的用法其他的对目录或者文件常用API3-1Unix/Linux地址空间代码段存储可执行指令的区域数据段:初始化为非零的数据BSS:初始化为零的数据堆动态内存向上增长栈分配本地变量的地方大部分体系结构上是向下增长的3-1Unix/Linux地址空间3-1Unix/Linux地址空间使用ch05-memaddr程序演示3-1系统调用sbrk和brk#includeunistd.h#includemalloc.hintbrk(void*end_data_segment);void*sbrk(ptrdiff_tincrement);绝对逻辑地址,这个地址代表地址空间新的结尾要增加的字节数char*p=(char*)sbrk(0);if(brk(p+32)0){/*handleerror*/}如果参数为0,即是取得当前地址空间的结尾实际上,你将不会用到这些调用3-2存储分配程序malloc分配空间的特点动态分配不一定连续空闲存储空间以空闲块链表的方式长度下一块的指针指向自身存储空间的指针块按照存储空间的升序组织3-2存储分配程序3-2存储分配程序分配算法首次适应第一个满足条件的存储块最佳适应找到最小满足条件的存储块释放算法找到合适的位置如果相邻的地址空间也为空闲,则需要合并,防止碎片3-2存储分配程序动态分配要满足体系结构的对齐要求Alignment对于32位risc机器一般是4bytes.通过如下的方式简化要求typedeflongAlign;unionheader{struct{unionheader*ptr;unsignedsize;}s;Alignx;};联合中,A1ign字段永远不会被使用,它仅仅用于强制每个头部在最坏的情况下满足对齐要求。3-2存储分配程序3-2存储分配程序staticHeaderbase;staticHeader*freep=NULL;void*malloc(unsignednbytes){Header*p,*prevp;Header*moreroce(unsigned);unsignednunits;nunits=(nbytes+sizeof(Header)-1)/sizeof(header)+1;if((prevp=freep)==NULL){base.s.ptr=freep=prevp=&base;base.s.size=0;}为了分配体系结构对其的内存大小第一次分配,取的链表的头部为&base.3-2存储分配程序for(p=prevp-s.ptr;;prevp=p,p=p-s.ptr){if(p-s.size=nunits){if(p-s.size==nunits)prevp-s.ptr=p-s.ptr;else{p-s.size-=nunits;p+=p-s.size;p-s.size=nunits;}freep=prevp;return(void*)(p+1);}if(p==freep)if((p=morecore(nunits))==NULL)returnNULL;}向操作系统申请存储空间,因为开销较大,所以每次至少申请NALLOC单元,较大的块分成较小的插入到free链表中。建立free的链表后,返回for循环查询链表再进行内存分配在空闲链表中检查,如果空间满足要求则返回分配的地址。(在末尾部分分配)。3-2存储分配程序#defineNALLOC1024/*最小申请单元*//*morecore:向系统申请更多的存储空间*/staticHeader*morecore(unsignednu){char*cp,*sbrk(int);Header*up;if(nuNALLOC)nu=NALLOC;cp=sbrk(nu*sizeof(Header));if(cp==(char*)-1)returnNULL;up=(Header*)cp;up-s.size=nu;free((void*)(up+1));returnfree
本文标题:第五章 Linux系统接口
链接地址:https://www.777doc.com/doc-3973650 .html