B站链接视频学习:Linux系统程序设计--线程_哔哩哔哩_bilibili
1.标准C的IO
c库标准头文件位置 `/usr/include`
typedef struct iobuf{
int cnt; /** 剩余的字节数 */
char *ptr; /** 下一个字符的位置 */
char *base; /** 缓冲区的位置 */
int flag; /** 文件访问模式 */
int fd; /** 文件描述符,内核提供 */
//......
}FILE;
2.缓存类型
**全缓存**
要求填满整个缓冲区后才进行IO系统调用。对于磁盘文件通常使用全缓存访问;
- **行缓存**
涉及一个终端时(标准输入输出)使用行缓存
行缓存满或碰到换行符自动输出;
- **无缓存**
标准错误流stderr通常是不带缓存的,这样可以使错误消息尽快地显示出来;
3.文件描述符
对于内核而言,所有打开文件都由文件描述符引用,文件描述符是一个非负的整数。
当打开一个现存文件或创建一个新文件时,内核向进程返回一个文件描述符。
在POSIX应用程序中,整数0,1,2被替换成符号常数STDIN_FILENO,STDOUT_FILENO和STDERR_FILENO;它们在头文件 `#include <unistd.h>` 中定义;
文件描述符的范围是0-OPEN_MAX;linux为024;
文件描述符与FILE的互转:
FILE *fdopen(int fd,const char *mode); //将文件描述符转FILE指针;
int fileno(FILE *stream); // 将文件指针转成文件描述符;
4.文件IO的系统调用
1. [open](#open)
2. [read](#read)
3. [write](#write)
4. [lseek](#lseek)
5. close
5.IO处理
1)**阻塞的IO模型**
若所调用的IO函数没有完成相关的功能就会使进程挂起,直到相关数据到达才会返回;常见终端、网络设备访问;
2) **非阻塞的IO模型**
当请求的IO操作不能完成时,则不让进程休眠,而且返回一个错误;
3)**IO多路转换模型**
如果请求的IO操作阻塞,且他不是真正阻塞IO,而且让其中一个函数等待,在这期间,IO可以进行其它操作;
4) **信号驱动的IO模型**
在这种模型下,通过安装一个信号处理程序,系统可以自动捕获特定信号的到来,从而启动IO;
5) **异步的IO模型**
在这种模型下,当一个描述已经准备好,可以启动IO时,进程会通知内核。由内核进行后续处理;
6.文件属性
struct stat {
dev_t st_dev; /* 包含文件的设备的ID */
ino_t st_ino; /* i节点数 */
mode_t st_mode; /* 文件类型及权限 */
nlink_t st_nlink; /* 硬链接数 */
uid_t st_uid; /* 所有者的用户ID */
gid_t st_gid; /* 所有者的组ID */
dev_t st_rdev; /* 设备ID(如果是特殊文件) */
off_t st_size; /* 总大小(bytes) */
blksize_t st_blksize; /* 文件系统I/O的块大小 */
blkcnt_t st_blocks; /* 分配的512B块数 */
struct timespec st_atim; /* 上次访问时间 */
struct timespec st_mtim; /* 上次修改时间 */
struct timespec st_ctim; /* 上次状态更改时间 */
};
7.文件属性与操作函数
[lstat](#lstat) 函数类似于stat,但是当命名的文件是一个符号链接时,lstat返回该符号链接的相关信息而不是该符号引用的文件信息;
文件操作相关的最基本元素有:目录结构(目录项)、索引节点(i node)、文件数据本身
8.文件类型
在linux中有七种文件类型对应七种宏:
| 序号 | 文件类型 | 宏 |
| 1 | 普通文件(regular file) | S_ISREG() |
| 2 | 目录文件(directory file) | S_ISDIR() |
| 3 | 块特殊文件(block special file) | S_ISBLK() |
| 4 | 字符特殊文件(chatacter special file) | S_ISCHR() |
| 5 | FIFO(named pipe) | S_ISFIFO() |
| 6 | 套接字(socket) | S_ISSOCK() |
| 7 | 符号链接(symbolic link) | S_ISLNK() |
9.文件权限
- **九种文件访问权限位**
1. 用户(拥有者)权限
S_IRUSR、S_IWUSR、S_IXUSR
2. 组权限
S_IRGRP、S_IWGRP、S_IXGRP
3. 其它权限
S_IROTH、S_IWOTH、S_IXOTH
10.fputs fprintf
int fputs( const char *s, FILE *fp ); // 把字符串 s 写入到 fp 所指向的输出流中。如果写入成功,它会返回一个非负值,如果发生错误,则会返回 EOF;
把字符串 s 写入到 fp 所指向的输出流中。如果写入成功,它会返回一个非负值,如果发生错误,则会返回 EOF
int main()
{
FILE *fp = NULL;
fp = fopen("test.txt", "w+");
fprintf(fp, "hello world...\n");
fputs("hello world2...\n",fp);
fclose(fp);
}
11.fgets fscanf
`char *fgets( char *buf, int n, FILE *fp )` 从 fp 所指向的输入流中读取 n - 1 个字符。它会把读取的字符串复制到缓冲区 buf,并在最后追加一个 null 字符来终止字符串。
如果这个函数在读取最后一个字符之前就遇到一个换行符 '\n' 或文件的末尾 EOF,则只会返回读取到的字符,包括换行符。
`int fscanf(FILE *fp, const char *format, ...)` 函数来从文件中读取字符串,但是在遇到第一个空格和换行符时,它会停止读取;
#include <stdio.h>
int main()
{
FILE *fp = NULL;
char buff[255];
fp = fopen("/tmp/test.txt", "r");
fscanf(fp, "%s", buff);
printf("1: %s\n", buff );
fgets(buff, 255, (FILE*)fp);
printf("2: %s\n", buff );
fgets(buff, 255, (FILE*)fp);
printf("3: %s\n", buff );
fclose(fp);
}