主要内容:文件输入/输出的系统调用。
在Linux中,万事万物皆文件。
文件描述符的概念
通用I/O模型的系统调用:
打开文件 open
关闭文件 close
向文件写数据 write
从文件读数据 read
这些系统调用不仅可以对普通的文件类型进行操作,也可以对管道、终端等所有类型的文件施以输入/输入操作。
所有执行I/O操作的系统调用都以文件描述符,一个非负整数(通常是小整数),来指代打开的文件。
用文件描述符表示所有类型的已打开文件,包括管道(pipe)、FIFO、socket、终端、设备和普通文件。(至今只操作过普通文件,其他几个类型还没接触过)
针对每个进程,文件描述符都自成一套。(没看懂)
3个标准的文件描述符
当在shell中操作的时候,有3个文件描述符始终是打开的。
在交互式的shell中,这个3个文件描述符通常指向shell运行所在的终端。(就是我们远程连接时候的屏幕?)
如果命令行制定对输入/输出进行重定向操作,那么shell会对文件描述符做适当修改,然后再启动程序。
文件描述符 用途 POSIX名称 stdio流
0 标准描述符 STDIN_FILENO stdin
1 标准输出 STDOUT_FILENO stdout
2 标准错误 STDERR_FILENO stderr
这里的意思是虽然shell开始会用0,1,2来这三个文件描述符代替标准输入,标准输入和标准错误,但是这种操作就像是给变量赋初始值一样。这些文件描述符并没有绑死,而是可以用freopen系统调用指向其他的任何文件对象。
fd = open(pathname, flags, mode)
打开pathname所标识的文件,并返回文件描述符,这个文件描述符就代表了打开的文件,并且在函数调用中用这个描述符就好了。
如果要打开的文件不存在,open()函数可以创建它,但是这取决于flags中的选项。
flags还指定了文件的打开方式:只读、只写或者是读写方式。
mode指定了由open()调用创建文件的访问权限(u,o,g,w, x,r),如果open()函数并没有创建文件,那么可以忽略或省略mode参数。
马丹,这块不熟,一个系统调用涉及到的东西这么多。
numread = read(fd, buffer, count)
从fd所指代的文件读取至多count字节的数据,并存储到buffer中。read()调用的返回值为实际读取到的字节数。如果再无字节可读(例如:读到文件结尾符EOF时),则返回0。
numwrite = write(fd, buffer, count)
从buffer中读取多达count字节的数据写入由fd指代的已打开文件中,write()调用的返回值为实际写入文件中的字节数,且有可能小于count。
status = close(fd)
在所有的输入/输出操作完成以后,调用close(),释放文件描述符fd以及与之相关的内核资源。
例子:用通用I/O系统调用实现一个简版的cp命令
1 #include <unistd.h> 2 #include <stdio.h> 3 #include <sys/stat.h> 4 #include <sys/types.h> 5 #include <fcntl.h> 6 7 int main(int argc, char **argv) { 8 int fd1, fd2, count=0; 9 char bufs[512]; 10 11 if(argc < 2) { 12 printf("Usage is error: ./mycp argv1 argv2. "); 13 return -1; 14 } 15 16 fd1 = open(argv[1], O_RDONLY, 0755); 17 if(fd1 < 0) { 18 printf("open %s error ", argv[1]); 19 return -1; 20 } 21 22 fd2 = open(argv[2], O_RDWR|O_CREAT, 0755); 23 if(fd2 < 0) { 24 printf("open %s error ", argv[2]); 25 return -1; 26 } 27 28 while( (count = read(fd1, bufs, 100)) > 0) { 29 write(fd2, bufs, count); 30 } 31 close(fd1); 32 close(fd2); 33 }
然后,顺手写了一个简单的Makefile,因为这几天在看make。
# this is my Makefile for mycp mycp: mycp.o cc -o mycp mycp.o mycp.o: cp.c cc -c cp.c -o mycp.o .PHONY: clean clean: -rm mycp mycp.o
好像代码插件没有Makefile,那就先用bash的风格吧