Linux文件与I/O操作Linux文件与I/O操作AndrewHuangbluedrum@163.com课程内容l系统调用l底层库函数l标准库函数l目录与文件维护系统调用lLinux大部分的系统功能是通过系统调用(SystemCall)来实现的.如open,send之类.l这些函数在C程序调用起来跟标准C库函数(printf…)非常类似.但是实现机制完全不同.l库函数仍然是运行在Linux用户空间程序.很多时候内部会调用系统调用.l但系统调用是内核实现的.在C库封装成函数.但通过系统软中断进行调用.–用time命令测试时间,系统时间实际就是系统调用时间累积ltime./demo1–用strace可以跟踪一种程序系统调用使用情况lstrace./demo1#不需要调试信息两者关系l可以参考C库函数malloc与系统调用sbrk的关系PDF文件使用pdfFactory试用版本创建操作常见C标准库函数lprintf,getch,scanflstrcpy,strcmp,strlenlmemcpy,memcmp,memsetlfopen,fwrite,fread常见系统调用函数l进程控制:fork(),waitpid()l文件控制open(),write()l网络收发函数socket(),bind(),send(),write()l权限控制access()l标准C的函数,应该在MSDN和Linux下的man都能同时查找联机帮助–并且声明定义在stdlib.h当中l而Linux系统调用只能用man查找相应帮助–大部分声明定义在unistd.h当中文件控制1.Linux文件结构lLinux环境中的文件具有特别重要的意义,因为它们为操作系统服务和设备提供了一个简单而统一的接口.在Linux中,一切(或几乎一切)都是文件。l通常程序完全可以像使用文件那样使用磁盘文件、串行口、打印机和其他设备。l大多数情况下,你只需要使用五个基本的函数——open、close、read、write和ioctllLinux中的任何事物都可以用一个文件代表,或者可以通过特殊的文件进行操作。l一些特殊文件–目录–设备文件–/dev/console–/dev/tty–/dev/null2.底层库函数lLinux在底层实现一整套处理文件函数.–这一些函数能处理普通文件,网络socket文件,设备文件等–全部是系统调用实现的函数l文件处理函数–open–打开或创建一个文件–creat–建立一个空文件–close–关闭一个文件–read–从文件读入数据–write–向文件写入一个数据–lseek–在文件中移动读写位置PDF文件使用pdfFactory试用版本创建操作–unlink–删除一个文件–remove–删除一个文件本身–fcntl–控制一个文件属性文件描述符l值为一个非负整数l用于表示一个打开文件l在内核空间被引用,并且由系统调用(open)所创建lread,write使用文件描述符l内核缺省打开三个文件描述符–1-标准输出–2-错误输出–0-标准输入1)open–--打开或创建一个文件open(打开文件)相关函数read,write,fcntl,close,link,stat,umask,unlink,fopen包含文件#includesys/types.h#includesys/stat.h#includefcntl.h定义函数intopen(constchar*pathname,intflags);intopen(constchar*pathname,intflags,mode_tmode);函数说明参数pathname指向欲打开的文件路径字符串。flags标志位,参见下一页返回值若所有欲核查的权限都通过了检查则返回0值,表示成功,只要有一个权限被禁止则返回-1。范例#includeunistd.h#includesys/types.h#includesys/stat.h#includefcntl.hmain(){intfd,size;chars[]=”LinuxProgrammer!\n”,buffer[80];fd=open(“/tmp/temp”,O_WRONLY|O_CREAT);write(fd,s,sizeof(s));close(fd);fd=open(“/tmp/temp”,O_RDONLY);size=read(fd,buffer,sizeof(buffer));PDF文件使用pdfFactory试用版本创建操作close(fd);printf(“%s”,buffer);}open的标志位lflags可以去下面的一个值或者是几个值的组合.–O_WRONLY以只写方式打开文件–O_RDONLY以只读方式打开文件–O_RDWR以可读写方式打开文件。上述三种旗标是互斥的,也就是不可同时使用,但可与下列的旗标利用OR(|)运算符组合。–O_CREAT若欲打开的文件不存在则自动建立该文件。–O_EXCL如果O_CREAT也被设置,此指令会去检查文件是否存在。文件若不存在则建立该文件,否则将导致打开文件错误。此外,若O_CREAT与O_EXCL同时设置,并且欲打开的文件为符号连接,则会打开文件失败。–O_TRUNC若文件存在并且以可写的方式打开时,此旗标会令文件长度清为0,而原来存于该文件的资料也会消失。–O_APPEND当读写文件时会从文件尾开始移动,也就是所写入的数据会以附加的方式加入到文件后面。–O_NONBLOCK以不可阻断的方式打开文件,也就是无论有无数据读取或等待,都会立即返回进程之中。多进程open同一个文件lopen的打开的文件描述符,只在同一进程内是唯一的.换句话说,不同程序打开同名文件将会产生不同的描述符.l不同进程写同一个文件会产生互相覆盖情况,大部分情况是无法预知.这是相当危险的情况,一般要加入互锁和进程间通讯来防止这种情况发生.openmode标志位情况l如果使用了O_CREATE标志,那么我们要使用open的第二种形式.,mode用来表示文件的访问权限.(sys/stat.h.中定义)–S_IRUSR用户可以读S_IWUSR用户可以写–S_IXUSR用户可以执行S_IRWXU用户可以读写执行–S_IRGRP组可以读S_IWGRP组可以写–S_IXGRP组可以执行S_IRWXG组可以读写执行PDF文件使用pdfFactory试用版本创建操作–S_IROTH其他人可以读S_IWOTH其他人可以写–S_IXOTH其他人可以执行S_IRWXO其他人可以读写执行–S_ISUID设置用户执行IDS_ISGID设置组的执行IDl我们也可以用数字来代表各个位的标志.Linux总共用5个数字来表示文件的各种权限.00000.第一位表示设置用户ID.第二位表示设置组ID,第三位表示用户自己的权限位,第四位表示组的权限,最后一位表示其他人的权限.open返回值l错误代码–成功打开文件返回文件描述符,否则返回一个负数–EEXIST参数pathname所指的文件已存在,却使用了O_CREAT和O_EXCL标志。–EACCESS参数pathname所指的文件不符合所要求测试的权限。–EROFS欲测试写入权限的文件存在于只读文件系统内。–EFAULT参数pathname指针超出可存取内存空间。–EINVAL参数mode不正确。–ENAMETOOLONG参数pathname太长。–ENOTDIR参数pathname不是目录。–ENOMEM核心内存不足。–ELOOP参数pathname有过多符号连接问题。–EIOI/O存取错误。2)close–关闭一个文件close(关闭文件)相关函数open,fcntl,shutdown,unlink,fclose表头文件#includeunistd.h定义函数intclose(intfd);函数说明当使用完文件后若已不再需要则可使用close()关闭该文件,二close()会让数据写回磁盘,并释放该文件所占用的资源。参数fd为先前由open()或creat()所返回的文件描述词。返回值若文件顺利关闭则返回0,发生错误时返回-1。错误代码EBADF参数fd非有效的文件描述词或该文件已关闭。附加说明虽然在进程结束时,系统会自动关闭已打开的文件,但仍建议自行关闭文件,并确实检查返回值。PDF文件使用pdfFactory试用版本创建操作范例参考open()close系统调用说明lclose调用终止一个文件描述符fildes与其对应文件之间的关联。文件描述符被释放并能够重新使用。close调用成功就返回0,出错就返回-1。l有时检查close调用的返回结果十分重要。有的文件系统,特别是网络文件系统,可能不会在关闭文件之前报告文件写操作中出现的错误,因为执行写操作时,数据可能未被确认写入。l运行中的程序能够一次打开的文件数目是有限制的。这个限制由头文件limits.h中的OPEN_MAX常数定义,它会随着系统的不同而不同,但POSIX规范要求它至少要为16。这个限制本身还会受到本地系统全局性限制的影响。3)write–向文件写入一个数据write(将数据写入已打开的文件内)相关函数open,read,fcntl,close,lseek,sync,fsync,fwrite表头文件#includeunistd.h定义函数ssize_twrite(intfd,constvoid*buf,size_tcount);函数说明write()会把参数buf所指的内存写入count个字节到参数fd所指的文件内。当然,文件读写位置也会随之移动。返回值如果顺利write()会返回实际写入的字节数。当有错误发生时则返回-1,错误代码存入errno中。错误代码EINTR此调用被信号所中断。EAGAIN当使用不可阻断I/O时(O_NONBLOCK),若无数据可读取则返回此值。EADF参数fd非有效的文件描述词,或该文件已关闭。范例请参考open()。write系统调用说明l系统调用write的作用是,把缓冲区buf的前nbytes个字节写入与文件描述符fildes关联的文件中。它返回实际写入的字节数。如果文件描述符有错或者底层的设备驱动程序对数据块长度比较敏感,该返回值可能会小于nbytes。如果这个函数的返回值是0,就表示未写出任何数据,如果是-1,就表示在write调用中出现了错误,对应的错误代码保存在全局变量errno里面。–参见simple_write.c–write可能会报告说它写入的字节比你要求的少。这并不一定是个错误。在程序中,你需要检查errno以发现错误,然后再次调用write写入剩余的数据。l当write写入成功后,当前写入指针会自动移到所写入最后一个字节下一个位置,相当于自动调用一次lseek(fd,count,SEEK_CUR);这样设计主要是为了方便了连续写入方便.PDF文件使用pdfFactory试用版本创建操作read从文件读出数据read(由已打开的文件读取数据)相关函数readdir,write,fcntl,close,lseek,readlink,fread表头文件#includeunistd.h定义函数ssize_tread(intfd,void*buf,size_tcount);函数说明read()会把参数fd所指的文件传送count个字节到buf指针所指的内存中。若参数count为0,则read()不会有作用并返回0。返回值为实际读取到的字节数,如果返回0,表示已到达文件尾或是无可读取的数据,此外文件读写位置会随读取到的字节移动。附加说明如果