Linux系统编程_文件I/O

本文详细介绍了Linux系统编程的学习路径,包括文件I/O、进程、线程、网络编程等内容,并推荐了多本经典参考书籍。此外,还深入探讨了如write函数的工作原理、open函数的使用技巧等细节。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Linux系统编程阶段的学习内容:

  1. 文件I/O
  2. 文件系统
  3. 进程
  4. 进程间通信
  5. 信号!
  6. 进程间关系,守护进程
  7. 线程
  8. 线程同步!
  9. 网络基础
  10. socket编程
  11. 高并发服务器!
  12. shell编程,正则表达式

参考书:
《Unix环境高级编程》W. Richard Stevens(!)
《TCP/IP详解》(3卷)(!)
《UNIX网络编程》(2卷)(!)
《Linux系统编程》Robert Love
《Linux/UNIX系统编程手册》Michael Kerrisk
《Unix内核源码剖析》青柳隆宏
《Linux内核源代码情景分析》
《Linux内核设计与实现》
《深入理解Linux内核》

权威资源:
man pages
开源中国论坛
O’REILLY出版社书籍


  • write函数并不是真正的系统调用,而是对系统调用sys_write的浅封装,即write函数内部的实现细节和sys_write内部一样,只是改了名字而已。这样做是为了对用户程序隐藏系统调用的实现细节。
  • open函数:
  1. 在open函数中通过宏O_CREAT创建新文件时,新文件的权限和第三个参数mode以及系统的umask值相关,权限为:mode & ~umask
  2. 文件读写权限:O_RDONLY\O_WRONLY\O_RDWR三选一
  3. 参数2的其他重要宏:O_TRUNC\O_NONBLOCK\O_EXCL\O_APPED
  4. open函数常见错误:(遇到不同错误时open函数返回的文件描述符值也不同)
    1)打开文件不存在
    2) 以写方式打开只读文件(打开文件没有对应权限)
    3)以只写方式打开目录
  • 文件描述符
  1. 进程控制块(PCB)
    关于可执行文件./a.out的内存布局
  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 函数返回值:

    1. 返回非零值: 实际read到的字节数

    2. 返回 -1:

      • errno != EAGAIN (或!= EWOULDBLOCK) read出错;
      • errno == EAGAIN (或== EWOULDBLOCK) 设置了非阻塞读,并且没有数据到达。
    3. 返回0:读到文件末尾

  • lseek函数:
    常用应用:

    1. 使用lseek拓展文件:write操作才能实质性的拓展文件。单lseek是不能进行拓展的。
      一般:write(fd, “a”, 1);
      od -tcx filename 查看文件的16进制表示形式
      od -tcd filename 查看文件的10进制表示形式

    2. 通过lseek获取文件的大小:lseek(fd, 0, SEEK_END);

    3. 【最后注意】:lseek函数返回的偏移量总是相对于文件头而言。

  • fcntl函数
    改变一个【已经打开】的文件的 访问控制属性。
    重点掌握两个参数的使用,F_GETFLF_SETFL
    例如:修改打开的文件fd的读写属性为非阻塞

flags = fcntl(fd, F_GETFL);
flags |= O_NONBLOCK;
fcntl(fd, F_SETFL, flags);
//或可简写为:
fcntl(fd, F_SETFL, O_NONBLOCK);
  • 位图(bitmap):linux中采用位图描述文件属性。fcntl函数的返回值是一个int值,表示一个32位的bitmap,其中的每一位描述该文件的一种文件属性,当要设置文件的某一属性时,采用位或操作。比如:假设flagsfcntl函数操作某一文件的返回值,flags |= O_NONBLOCK

  • 传入传出参数(value-result)

  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)全缓冲,把缓冲区填满后才输出。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值