Linux系统编程阶段的学习内容:
- 文件I/O
- 文件系统
- 进程
- 进程间通信
- 信号!
- 进程间关系,守护进程
- 线程
- 线程同步!
- 网络基础
- socket编程
- 高并发服务器!
- shell编程,正则表达式
- write函数并不是真正的系统调用,而是对系统调用sys_write的浅封装,即write函数内部的实现细节和sys_write内部一样,只是改了名字而已。这样做是为了对用户程序隐藏系统调用的实现细节。
- 在open函数中通过宏O_CREAT创建新文件时,新文件的权限和第三个参数mode以及系统的umask值相关,权限为:
mode & ~umask。 -
open函数的常见错误:(遇到不同错误时open函数返回的文件描述符值也不同)
- 打开文件不存在
- 以写方式打开只读文件(打开文件没有对应权限)
- 以只写方式打开目录
文件描述符:
(1)进程控制块(PCB)
(2)文件描述符表
结构体PCB 的成员变量file_struct *file 指向文件描述符表。从应用程序使用角度,该指针可理解记忆成一个字符指针数组,下标0/1/2/3/4…找到文件结构体。本质是一个键值对,0、1、2…都分别对应具体地址。但键值对使用的特性是自动映射,我们只操作键不直接使用值。新打开文件返回文件描述符表中未使用的最小文件描述符。预读入缓输出机制:
read、write函数被称为Unbuffered I/O,指的是无用户级缓冲,但不保证不使用内核缓冲区。比如,同样是实现文件拷贝命令cp的实现,若用系统调用read、wirte每次拷贝一个字节来实现比用C标准库函数fgetc、fputc来实现的运行时间要慢得多,原因就是read和write没有(用户级)缓冲区,而用fgetc、fputc来实现虽然每次只能拷贝一个字节但它们有缓冲区,这样就大大减少了用户区向内核区的切换。这种机制称为预读入缓输出。用户级缓冲区和系统缓冲区默认大小都是4096字节。-
阻塞和非阻塞:
总结read 函数返回值:- 返回非零值: 实际read到的字节数
- 返回 -1: 1):errno != EAGAIN (或!= EWOULDBLOCK) read出错; 2):errno == EAGAIN (或== EWOULDBLOCK) 设置了非阻塞读,并且没有数据到达。
- 返回0:读到文件末尾
-
lseek常用应用:
使用lseek拓展文件:write操作才能实质性的拓展文件。单lseek是不能进行拓展的。
一般:write(fd, “a”, 1);
od -tcx filename 查看文件的16进制表示形式
od -tcd filename 查看文件的10进制表示形式-
通过lseek获取文件的大小:lseek(fd, 0, SEEK_END);
【最后注意】:lseek函数返回的偏移量总是相对于文件头而言。
fcntl函数
改变一个【已经打开】的文件的 访问控制属性。
重点掌握两个参数的使用,F_GETFL 和 F_SETFL。位图(bitmap):linux中采用位图描述文件属性。
fcntl函数的返回值是一个int值,表示一个32位的bitmap,其中的每一位描述该文件的一种文件属性,当要设置文件的某一属性时,采用位或操作。比如:假设flags是fcntl函数操作某一文件的返回值,flags |= O_NONBLOCK。-
传入传出参数
1)传入参数: const 关键字修饰的 指针变量 在函数内部读操作。 比如,char *strcpy(cnost char *src, char *dst);中的第一个参数。
2)传出参数:- 指针做为函数参数
- 函数调用前,指针指向的空间可以无意义,调用后指针指向的空间有意义,且作为函数的返回值传出
- 在函数内部写操作。
比如,char *strcpy(cnost char *src, char *dst);中的第二个参数。
3)传入传出参数:
- 调用前指向的空间有实际意义
- 调用期间在函数内读、写(改变原值)操作
- 作为函数返回值传出。
标准I/O提供了三种类型的缓冲:全缓冲、行缓冲、无缓冲,目的是尽量减少使用read和write的次数。
(1)无缓冲,比如标准错误stderr,任何传输到它的出错信息都会立刻打印出来;
(2)行缓冲,比如printf函数,在换行之前会一直把打印的内容存到标准输出缓冲区中,直至换行或者调用fflush函数刷新标准输出stdout;
(3)全缓冲,把缓冲区填满后才输出。