Linux_高级程序_I/O操作 知识点备忘
1. Linux I/O操作类别
1.1 底层输入输出
1.2文件系统接口
1.3 管道及FIFO(队列)
1.4 Socket
1.5 底层终端接口(tty)
2. 主要数据结构
2.1 FD
2.2 File
2.3 Files Structure
3 底层输入输出开发实例
3.1 打开(建立)和关闭文件
Open(Posix C) | 打开文件 |
---|---|
头文件 | #include<sys/types.h> ,#include<sys/stat.h>,#include<fcntl.h> |
函数原型 | int open(const char *pathname,int flags,int perms) |
参数 | (pathname:被打开的文件名)----(flag:文件被打开的方式:ORDONLY,O_TRUNC,O_APPEND,也可数字)----(perms:被打开的文件的存储权限:S_I(R/W/X)(USR/GRP/OTH),也可数字) |
返回值 | 成功返回文件描述符,失败返回-1 |
Close | 关闭文件 |
---|---|
头文件 | #include<unistd.h> |
函数原型 | int close(int fd) |
参数 | fd:文件描述符 |
返回值 | 成功返回0,失败返回-1 |
首先输入所有需要的头函数,其中umask为4位数为UID,USR,GRP,OTH,其中UID为针对用户设置权限,一般定义为0.需先将掩码设置为0000.
关闭文件只需对执行close函数即可。
//文件名字为file_openclose.c,执行以下步骤
gcc file_openclose.c -o fileopenclose //编译
./fileopenclose hello1 //执行fileopenclose文件,若不输入hello将提示请输入文件名。
3.2读写文件(注意创建文件时,umask以及文件的权限,防止文件权限不够例如只读无法写入信息)
Read | 读取文件 |
---|---|
头文件 | #include<unistd.h> |
函数原型 | ssize_t read(int fd,void *buf,size_t count) |
参数 | (fd:文件描述符)----(buf:指定存储器读出数据的缓冲区)----(count:读出指定的字节数) |
返回值 | 成功返回读到的字节数,0:达到文件结尾,失败返回-1 |
首先创建一个buff字符串,并分配空间,读取已有文件tc111.txt内部的数据,保存至buf并打出buf字符串
//文件名字为file_read.c,执行以下步骤
gcc file_read.c -o fileread //编译
./fileread tc111.txt //执行fileread文件,若不输入tc111.txt将提示请输入文件名。
- 步骤总结为:1打开文件----2分配buf----3读文件至buf----4打印buf----5close文件
write | 写文件 |
---|---|
头文件 | #include<unistd.h> |
函数原型 | ssize_t write(int fd,void *buf,size_t count) |
参数 | (fd:文件描述符)----(buf:指定存储器读出数据的缓冲区)----(count:读出指定的字节数) |
返回值 | 成功返回读到的字节数,失败返回-1 |
编译并且执行文件,将内容写入hello2.txt
3.3 设置文件位置
lseek | 设置文件位置 |
---|---|
头文件 | #include<unistd.h>----#include <sys/types.h> |
函数原型 | off_t lseek(int fd,off_t offset,int whence) |
参数 | (fd:文件描述符)----(offset:偏移量。单位是字节,可正可负(正前移负后移))----(whence:当前位置的基点:SEEK_SET,SEEK_CUR,SEEK_END) |
返回值 | 成功返回文件相对于头的位移量,失败返回-1 |
编译并执行,将内容写入hello3.txt
3.3.1 读写–demo
要求:将file.in中的内容读写(没有则创建)到file.out中
3.4 文件符号和流
3.5 快速聚集I/O
3.6 内存映射I/O
3.7 同步I/O操作
3.8 文件锁定
3.9 中断驱动输入
4 标准输入输出开发实例
4.1 Linux调用层次结构
4.2 Linux内核功能划分
- Process Scheduler,也称作进程管理、进程调度。
- Memory Manager,内存管理。中,需要使用的时候,再取回到内存中。
- VFS(Virtual File System),虚拟文件系统。
- Network,网络子系统。
- IPC(Inter-Process Communication),进程间通信。
4.3系统调用的过程
4.4添加新的系统调用
1.修改系统调用表
2.添加系统调用对应的内核函数声明
3.添加系统调用对应的内核函数定义
以arm平台为例
- 1修改系统调用表:更新/arch/arm/kernel/call.S
- 2系统调用对应的内核函数声明:更新/include/linux/syscalls.h
- 3添加系统调用对应的内核函数定义:在内核源码目录中添加或是指定一个源文件,然后在该源文件中添加。
4.5标准I/O函数
-
文件I/O:不带缓存的IO(unbuffered I/O)。直接调用系统kernel。
-
标准I/O:标准I/O是ANSI C建立的一个标准I/O模型,是一个标准函数包和stdio.h头文件中的定义,具有一定的可移植性。标准I/O库处理很多细节。例如缓存分配,以优化长度执行I/O等。标准的I/O提供了三种类型的buffer。
(1)全缓存:当填满标准I/O缓存后才进行实际的I/O操作。
(2)行缓存:当输入或输出中遇到新行符时,标准I/O库执行I/O操作。
(3)不带缓存
各自的使用函数
底层I/O | 标准I/O | |
---|---|---|
打开 | open | fopen,freopen,fdopen |
关闭 | close | fclose |
读 | read | getc,fgetc,getchar,fgets,gets,fread |
写 | write | putc,fputc,putcharfputs,puts,fwrite |
- 打开文件 FILE* fp=fopen(const char* path,const char *mod)
其中path是文件名,mod用于指定文件打开的模式的字符串,比如"r",“w”,“w+”,"a"等等,可以加上字母b用以指定以二进制模式打开。成功则返回一个FILE文件指针,失败返回NULL,这里的文件指针并不是指向实际的文 件,而是一个关于文件信息的数据包,其中包括文件使用的缓冲区信息 - 关闭文件 fclose(fp):成功返回0,失败返回EOF(底层I/O返回-1)
- 读文件 char *fgets(char *s, int size, FILE *stream);s用于存储输入的地址,size表示输入字符串的最大长度,stream表示文件指针,指向要读取的文件。
- 写文件 与读文件相对应的,标准C语言I/O使用putc写入字符,比如:
putc(ch,fp);
第一个参数是字符,第二个是文件指针。而fputs与此类似:
fputs(buf,fp);
仅仅是第一个参数换成了字符串地址。而fprintf与printf类似,增加了一个参数用于指定写入的文件,比如:
fprintf(stdout,“Hello %s.\n”,“dennis”);
切记fscanf和fprintf将FILE指针作为第一个参数,而putc,fputs则是作为第二个参数。 - 随机存取 int fseek(FILE *stream, long offset, int whence),stream是文件指针,offset是long类型的偏移量(表示从起始点开始移动的距离)whence:SEEK_SET,SEEK_CUR,SEEK_END.
- 而ftell函数用于返回文件的当前位置,返回类型是一个long类型,比如下面的调用:
fseek(fp,0L,SEEK_END);//定位到结尾
----long last=ftell(fp); //返回当前位置
那么此时的last就是文件指针fp指向的文件的字节数。
4.5.1 标准I/O函数demo
要求:将file.in的内容拷贝至file.out中,若没有则创建。
编译然后执行