系统函数、系统调用
系统函数
open/close函数
函数原型
man 2 open
// open, creat - open and possibly create a file or device
// The argument flags must include one of the following access modes:
// O_RDONLY, O_WRONLY, or O_RDWR.
// 或者 O_APPEND O_CREAT O_EXCL O_TRUNC(清空文件)
int open(const char * pathname, int flags);
- 头文件
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
// --> 简写为
#include <unistd.h>
- demo
#include <stdio.h>
#include <fcntl.h> // O_RDONLY的头文件
#include <unistd.h>
int main()
{
int fd;
fd = open("./dict", O_RDONLY | O_CREAT);
// 创建文件指定权限,8进制数
fd = open("./dict", O_RDONLY | O_CREAT, 0644);
printf(fd);
close(fd);
return 0;
}
read/write函数
ssize read(int fd, void *buf, size_t count);
ssize write(int fd, const void *buf, size_t count);
read参数
- fd:文件描述符
- buf:存放数据的缓冲区
- count:缓冲区的大小
read返回值:
- success:读到的字节数
- fail:-1,设置errno
write返回值:
-
success:写入的字节数
-
error:-1
实现cp
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
int main(int argc, char *argv[])
{
char buf[1024];
int len = 0;
int fd1 = open(argv[1], O_RDONLY);
if(fd1 == -1)
{
perror("open argv1 error");
exit(1); // stdlib
}
// 打开文件,如果没有就创建,如有就清空
int fd2 = open(argv[2], O_RDWR | O_CREAT | O_TRUNC, 0664);
while((len = read(fd1, buf, 1024))!=0)
{
if(len < 0)
{
perror("read error!");
exit(1);
}
write(fd2, buf, len);
}
close(fd1);
close(fd2);
return 0;
}
跟踪系统调用
$ strace ./readWrite
read(-1, 0x7ffd53164ea0, 1024) = -1 EBADF (Bad file descriptor)
write(3, "", 18446744073709551615) = -1 EFAULT (Bad address)
read(-1, 0x7ffd53164ea0, 1024) = -1 EBADF (Bad file descriptor)
write(3, "", 18446744073709551615) = -1 EFAULT (Bad address)
read(-1, 0x7ffd53164ea0, 1024) = -1 EBADF (Bad file descriptor)
write(3, "", 18446744073709551615) = -1 EFAULT (Bad address)
read(-1, 0x7ffd53164ea0, 1024) = -1 EBADF (Bad file descriptor)
write(3, "", 18446744073709551615) = -1 EFAULT (Bad address)
库函数
fopen/fclose
fgetc/fputc
FILE *fp, *fp_out;
int n;
fp = fopen("./dict.txt", "rw");
if (fp == NULL) {
perror("fopen error");
exit(1);
}
fp_out = fopen("dict.cp", "w");
if (fp_out == NULL) {
perror("fopen error");
exit(1);
}
while ((n = fgetc(fp)) != EOF) {
fputc(n, fp_out);
}
fclose(fp);
fclose(fp_out);
文件描述符
文件描述符指向文件结构体.
PCB(进程控制块) :本质是结构体,成员是文件描述符,文件描述符:01/2/3...
一个进程快最多打开1024个文件,第一个文件是stdin
, 2->stdout
, 3 ->stderr
阻塞、非阻塞
阻塞:当读取设备文件、网络文件。读取常规文件不会阻塞。
设备目录:
- /dev/tty 【终端设备】
阻塞示例:
void block() {
char buf[10];
// 读取是个字节
int n = read(STDIN_FILENO, buf, 10);
if (n < 0) {
perror("read STDIN_FILENOO");
exit(1);
}
write(STDOUT_FILENO, buf, 10);
}
当以非阻塞的方式读取文件(设备文件或者网络文件),并且文件为空时,open函数返回-1,并且将errno 设置为 EAGAIN
or EWOULDBLOCK
tryagain:
n = read(fd, buf, 10);
if(n<0)
{
if(errno!= EAGAIN)
{
perror("read /dev/tty");
exit(1);
}
else
{
write(STDOUT_FILENO, "try again!", strlen("try again!"));
sleep(2);
goto tryagain;
}
}