系统调用IO接口
系统调用IO接口和标准库的IO接口的区别就在于他更加底层,权限更高,更加灵活直接,简单粗暴。和标准库IO接口一样,也对应了五个函数,分别是open、write、read、lseek和close,从名字就可以看出它的简单粗暴。
函数内容
1、open
函数声明为:
int open(const char*pathname,int flags,mode_t mode);
open函数和fopen一样,都是用于打开文件,但是其传递的参数不同,返回值也不同。pathname表示的是要打开的文件名称,flags表示的是打开方式,mode表示的是创建权限。
flags:flags也同样是open的核心,甚至是整个接口函数们的核心,因为他定下了一个大的方向,即该文件是要写还是读,是要追加还是创建。它的写法和fopen中的还不太一样,包含了两个部分,即必选项和可选项。
必选项 | 内容 |
---|---|
O_RDONLY | 只读 |
O_WRONLY | 只写 |
O_RDWR | 可读可写 |
可选项 | 内容 |
---|---|
O_CREAT | 若文件不存在,则创建,若文件存在,则打开 |
O_EXCL | 如果文件存在,则报错 |
O_TRUNC | 打开文件,并清空原有内容 |
O_APPEND | 追加写 |
mode为文件创建权限,也就是文件的8进制权限,具体就不展开了,如果要求使用O_CREAT,则一定要加0777.
返回值为成功返回一个非负整数,也就是文件描述符,需要重点区别文件描述符和fopen函数返回的文件流指针二者的区别。如果失败返回-1.
2、write
函数声明为:
ssize_t write(int fd, const void * buf, size_t nbyte)
其功能和fwrite一样,都是将buf中的数据写入fd中。此处fd就是open返回的文件操作句柄,buf就是写入的数据,nbyte就是写入文件的长度。
返回值为成功返回实际写入文件的数据长度,失败返回-1.
3、read
函数声明为:
ssize_t read (int fd, void * buf, size_t count);
其功能和fread一样,都是读取特定长度的数据到buf地址空间中,其中fd还是文件操作句柄,buf就是一块用于存放读取到的数据的空间缓冲区,count是写入文件的长度。
返回值为成功返回实际读取到的文件数据长度,失败返回-1,注意:如果返回0,则说明没有读取到数据。
4、lseek
函数声明为:
off_t lseek(int fd, off_t offset, int whence);
和fseek一样都是跳转文件偏移的位置。其中fd是文件操作句柄,offset是偏移量,whence是相对起始位置,和fseek的起始位置一样,也有三种常用的:
相对起始位置 | 内容 |
---|---|
起始位置 | SEEK_SET |
当前位置 | SEEK_CUR |
文件末尾位置 | SEEK_END |
返回值为成功返回跳转位置和起始位置的差值,因此可以用来测量文件长度,具体用法是直接跳转的文件末尾,取返回值。失败返回-1.
5、close
函数声明:
int close(int fd);
功能就是关闭fd中的文件。
返回值为成功返回0;失败返回-1。
代码实现
#include<stdio.h>
#include<unistd.h>
#include<fcntl.h>
#include<string.h>
int main()
{
int fd = open("./test.txt",O_RDWR|O_CREAT|O_APPEND,0777);
if (fd < 0)
{
perror("error\n");
return -1;
}
const char *ptr = "this is the input of text!";
int ret = write(fd,ptr,strlen(ptr));
if (ret < 0)
{
perror("error\n");
return -1;
}
char buf[1024] = {0};
lseek(fd,0,SEEK_SET);
ret = read(fd,buf,1023);
if (ret < 0)
{
perror("error!\n");
return -1;
}
printf("%d-%s\n",ret,buf);
close(fd);
return 0;
}
结果为: