学习几个常用的Linux系统I/O函数:open、close、write、read和lseek。注意,系统调用函数必须都考虑返回值。
(1)open函数的使用
首先,需要包含三个头文件:<sys/types.h> <sys/stat.h> <fcntl.h>
以如下代码为例:
[root@localhost src]# ls
add.c div.c hello main.c mul.c sub.c zsx zsx.c
[root@localhost src]# vim zsx.c
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h> //前三个头文件对应库函数open
#include <stdlib.h> //对应库函数exit
#include <stdio.h> //对应库函数 perror和printf
#include <unistd.h> //对应库函数closeint main( )
{int fd; //记录open函数返回值fd = open("zsxhello",O_RDWR); //以读写方式打开一个不存在的文件,当前目录printf("fd=%d\n",fd);if( fd == -1 ) //如果打开失败{perror("open zsxhello"); //则输出打开失败的原因(详细错误信息)exit(1); //并结束当前进程,则后面程序不再执行}//如果打开成功,继续向后执行 注意exit函数结束当前进程,在头文件stdlib.h中声明int ret = close( fd ); //打开后关闭该文件printf("ret=%d\n",ret);if( ret == -1 ) //如果关闭文件失败{perror("close zsxhello"); //输出出错的详细信息exit(1);}return 0;
}
[root@localhost src]# gcc -pipe -pedantic -Wall -ggdb3 zsx.c -o zsx
[root@localhost src]# ldd zsx
linux-vdso.so.1 => (0x00007fff21f18000)
libc.so.6 => /lib64/libc.so.6 (0x00007eff28730000)
/lib64/ld-linux-x86-64.so.2 (0x00007eff28b10000)
[root@localhost src]# ./zsx
fd=-1 //文件打开失败
open zsxhello: No such file or directory //错误详细信息
//下面说明如何利用open函数创建一个文件
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>int main( )
{int fd;fd = open("hello",O_RDWR); //打开一个已有的文件printf("fd=%d\n",fd);if( fd == -1 ){perror("open hello");}int fd1 = open("zsxhello",O_RDWR | O_CREAT,0777); //创建一个zsxhello文件printf("fd1=%d\n",fd1);if( fd1 == -1 ){perror("open zsxhello");}int ret = close( fd ); //关闭hello文件printf("ret=%d\n",ret);if( ret == -1 ){perror("close hello");}int ret1 = close( fd1 ); //关闭zsxhello文件printf("ret1=%d\n",ret1);if( ret1 == -1 ){perror("close zsxhello");}return 0;
}
[root@localhost src]# ./zsx
fd=3
fd1=4 //可以看到新打开的两个文件描述符为3、4
ret=0
ret1=0 //成功关闭文件
int fd1 = open("zsxhello",O_RDWR | O_CREAT,0777); //创建一个zsxhello文件
O_RDWR | O_CREAT 参数表示创建该文件,且以读写的方式打开 0777定义创建文件的权限,文件的权限都是8进制数(以0开头的数),0777等价于777。
[root@localhost src]# ls
add.c div.c hello main.c mul.c sub.c zsx zsx.c zsxhello
[root@localhost src]# ll zsxhello
-r-xr-xr-x. 1 root root 0 Mar 18 18:09 zsxhello
[root@localhost src]# umask //掩码,操作系统对文件的一种保护机制
0777
注意:可看到文件zsxhello的权限并不是0777,而是0555。这是因为文件的实际权限与掩码umask有关。因此,可以根据掩码值,来计算出相应的给定值,从而达到自己想要的最终实际值,也可以修改掩码: umask 0000 将掩码值修改为 0000
文件权限由open的mode参数和当前进程的umask掩码共同决定:
//利用open函数对文件进行截断 O_TRUNC参数
将文件截断就是将文件内容删除一部分,留一部分。将文件截断为0就是删除文件全部内容(清空)。代码如下:
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>int main( )
{int fd;fd = open("hello",O_RDWR | O_TRUNC); //以读写方式打开hello文件,并将其截断为0printf("fd=%d\n",fd);if( fd == -1 ){perror("open hello");exit(1); //若打开失败,退出当前进程,此时main函数返回值不再为0}int ret;ret = close( fd );printf("ret=%d\n",ret);if( ret == -1 ){perror("close hello");exit(1); //若关闭失败,退出当前进程,此时main函数返回值不再为0}return 0;
}
[root@localhost src]# ll hello
-rwxrwxrwx. 1 root root 14 Mar 18 16:58 hello
[root@localhost src]# ./zsx
fd=3
ret=0
[root@localhost src]# ll hello
-rwxrwxrwx. 1 root root 0 Mar 18 18:38 hello
注意上面代码:对于Linux系统I/O函数,都有返回值,且需要对返回值进行判断,并作出相应处理,如退出当前进程。
//利用open函数判断文件是否存在 O_CREAT与O_EXCL参数必须同时使用,即通过创建文件的方式来判断其是否存在,如果存在,出错,并给出提示。代码如下:
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>int main( )
{int fd;fd = open("hello",O_RDWR | O_CREAT | O_EXCL,0777); 判断hello文件是否存在 printf("fd=%d\n",fd);if( fd == -1 ){perror("open hello");exit(1);}int ret;ret = close( fd );printf("ret=%d\n",ret);if( ret == -1 ){perror("close hello");exit(1);}return 0;
}
[root@localhost src]# ./zsx
fd=-1
open hello: File exists
如果将fd = open("hello",O_RDWR | O_CREAT | O_EXCL,0777); 改为: fd = open("hello",O_RDWR | O_CREAT,0777); 仍然能正常打开已经存在的文件,对于不存在的文件则创建,执行结果:
[root@localhost src]# ./zsx
fd=3
ret=0
(2)close函数的使用
#include <unistd.h> //包含头文件
int close(int fd); //返回值为0或-1,0代表关闭文件成功,-1代表关闭文件失败。 参数为所要关闭文件的文件描述符。 关闭文件出错,则会赋值给errno一个对应的代码值。