Table of contents
2--Common functions of system I/O
3--The difference between standard I/O and system I/O
1--File descriptor
The essence of the file descriptor: an integer, an array subscript (the elements of the array point to the file structure);
The smallest file descriptor within the available range is used first ;
The file descriptor of standard input (stdin) is 0; the file descriptor of standard output (stdout) is 1; the file descriptor of standard error (stderr) is 2; therefore the remaining file descriptors must be >= 3;
2--Common functions of system I/O
The usage of the following commonly used functions can be viewed through the man manual;
open():
close():
read();
write();
int open(const char *pathname, int flags);
int close(int fd);
ssize_t read(int fd, void *buf, size_t count);
ssize_t write(int fd, const void *buf, size_t count);
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#define BUF_SIZE 1024
int main(int argc, char* argv[]){
int sfd, dfd;
char* buf[BUF_SIZE];
int len, ret, pos;
if(argc < 3){
fprintf(stderr, "Usage...\n");
exit(1);
}
sfd = open(argv[1], O_RDONLY);
if(sfd < 0){
perror("open()");
exit(1);
}
dfd = open(argv[2], O_WRONLY|O_CREAT, O_TRUNC, 0600);
if(dfd < 0){
close(sfd);
perror("open()");
exit(1);
}
printf("%d %d\n", sfd, dfd); // 3 4
while(1){
len = read(sfd, buf, BUF_SIZE);
if(len < 0 ){
perror("read()");
break;
}
if(len == 0) break;
pos = 0;
while(len > 0){
ret = write(dfd, buf+pos, len);
if(ret < 0){
perror("write()");
exit(1);
}
pos += ret;
len -= ret;
}
}
close(dfd);
close(sfd);
exit(0);
}
3--The difference between standard I/O and system I/O
The throughput of standard I/O is high (the data will be put into the buffer first , and the data access will be completed only after the buffer is refreshed), and the response speed of system I/O is fast (the data will not be put into the buffer, once Calling completes an operation);
It is best not to mix standard I/O and system I/O;
Conversion functions for standard I/O and system I/O: fileno() and fdopen() ;
int mian(){
putchar('a');
write(1, "b", 1);
putchar('a');
write(1, "b", 1);
putchar('a');
write(1, "b", 1);
}
// 程序会打印:bbbaaa
// 因为标准I/O打印的 a 会先放到缓冲区中,后面一次完成输出;
4--Atomic operations
Atomic operations: indivisible operations;
The role of atomic operations: resolving competition and conflicts;
5--dup() and dup2()
#include <unistd.h>
int dup(int oldfd);
int dup2(int oldfd, int newfd); // 原子操作
// dup 复制(准确来说,将当前文件描述符对于文件的权限共享过来给新的文件描述符了)当前的文件描述符
// dup 返回一个新的文件描述符,新旧文件描述符共享访问同一个文件
// dup 返回的新文件描述符一定是当前可用文件描述中的最小数值
// dup2是原子操作,不能被打断,它会关闭旧的文件描述符
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#define FNAME "./out"
int main(){
int fd = open(FNAME, O_WRONLY|O_CREAT|O_TRUNC, 0600);
if(fd < 0){
perror("open()");
exit(1);
}
// close(1); // 关闭标准输出
// dup(fd); // 关闭标准输出后,1成了最小的可用文件描述符,因此dup(fd)后,1和最初的fd共享打开的文件
dup2(fd, 1); // 原子操作,功能等同于上面两句
if(fd != 1){
close(fd);
}
// 上面语句的功能相当于是将文件描述符1映射到打开的文件,即打开文件的文件描述符 fd = 1
// puts默认打印到标准输出,但此时标准输出被关闭了
// 文件描述符1其实指向的是打开的文件,因此puts打印到了打开的文件里
puts("hello!");
exit(0);
}
6--fcntl() and ioctl()
#include <unistd.h>
#include <fcntl.h>
int fcntl(int fd, int cmd, ... /* arg */ );
// fcntl() performs one of the operations described below on the open file descriptor fd.
// The operation is determined by cmd.
// fcntl() 根据提供的 cmd 来对输入的 fd 进行相关操作
#include <sys/ioctl.h>
int ioctl(int fd, unsigned long request, ...);
// ioctl 是设备驱动程序中设备控制接口函数
// 一个字符设备驱动通常会实现设备打开、关闭、读、写等功能
// 在一些需要细分的情境下,如果需要扩展新的功能,通常以增设 ioctl() 命令的方式实现。