资讯动态

Linux系统编程-文件描述符

发布时间:2026/10/1 12:28:30 来源:尧图企业网站定制
一. 文件描述符1.1 文件描述符的概念本质文件描述符本质是一个整型数是一个数组的下标。其中默认打开数组的前三个 0STDIN_FILENO标准输入1STDOUT_FILENO标准输出2STDERR_FILENO标准出错注意文件描述符在使用时优先使用当前可用位置最小的。二. 阻塞与非阻塞2.1 概念读常规文件是不会阻塞的不管读多少字节read一定会在有限的时间内返回。从终端设备或网络读则不一定如果从终端输入的数据没有换行符调用read读终端设备就会阻塞如果网络上没有接收到数据包调用read从网络读就会阻塞至于会阻塞多长时间也是不确定的如果一直没有数据到达就一直阻塞在那里。同样写常规文件是不会阻塞的而向终端设备或网络写则不一定。现在明确一下阻塞Block这个概念。当进程调用一个阻塞的系统函数时该进程被置于睡眠Sleep状态这时内核调度其它进程运行直到该进程等待的事件发生了比如网络上接收到数据包或者调用sleep指定的睡眠时间到了它才有可能继续运行。与睡眠状态相对的是运行Running状态在Linux内核中处于运行状态的进程分为两种情况(1)、正在被调度执行。CPU处于该进程的上下文环境中程序计数器eip里保存着该进程的指令地址通用寄存器里保存着该进程运算过程的中间结果正在执行该进程的指令正在读写该进程的地址空间。(2)、就绪状态。该进程不需要等待什么事件发生随时都可以执行但CPU暂时还在执行另一个进程所以该进程在一个就绪队列中等待被内核调度。系统中可能同时有多个就绪的进程那么该调度谁执行呢内核的调度算法是基于优先级和时间片的而且会根据每个进程的运行情况动态调整它的优先级和时间片让每个进程都能比较公平地得到机会执行同时要兼顾用户体验不能让和用户交互的进程响应太慢。综上(1) 阻塞(Block)产生的场景读设备文件读网络文件。(读常规文件无阻塞特性)(2) 针对红色字体如果从终端输入的数据没有换行符调用read读终端设备就会阻塞做以下解释缓冲区有以下三种模式模式备注设备行缓冲换行/满了刷新也可强制刷新终端设备全缓冲满了刷新或者强制刷新默认只要不是终端设备。(比如文件)无缓冲需要立即输出的内容如stderr由于终端是行缓冲模式这就决定了输入的数据没有换行符就会一直阻塞。(3)阻塞是文件的属性(针对设备文件与网络文件)不是readwrite函数的属性。eg终端文件/dev/tty----默认是阻塞属性。2.2 代码示例2.2.1 阻塞2.2.2 修改文件阻塞属性若要修改终端文件的阻塞属性则要使用open函数以非阻塞(O_NONBLOCK)的形式打开终端文件。这里有一个重点在read函数那一块说到函数读取失败时返回值为-1并且设置errno。但是当read读取一个非阻塞形式的文件时并且没有数据可读时也返回-1errno被设置为EAGAIN或者EWOULDBLOCK(二者相等)这种情况并不是读取失败情况故需 要对返回值以及errno的值加以判断三. 重定向3.1 重定向命令cat 12_dup.c testcat 12_dup.c test //以追加方式重定向eg以下是顺序执行这三条指令后test3中的内容3.2 重定向函数3.2.1 dup函数作用dup() 系统调用会创建一个与文件描述符 oldfd 相同的副本同时会使用编号最小且尚未被使用的文件描述符来作为新描述符。返回值成功返回一个新的文件描述符失败返回-1并且设置errno原理eg执行之前的test执行之后的test3.2.2 dup2函数作用dup2() 系统调用的功能与 dup() 相同但其不同之处在于它并非使用未被占用的最小文件描述符编号而是使用 newfd 中指定的文件描述符编号。如果文件描述符 newfd 之前已处于打开状态那么在重新使用之前它会被自动关闭。如果oldfdnewfd则dup2函数什么也不做返回newfd本身。返回值成功返回一个新的文件描述符newfd失败返回-1并且设置errnoeg3.2.3 dup函数的缺点缺点操作不原子。原子操作不可被分割的操作。 作用解决竞争和冲突。(要么没做要么一步做完)上面这个例子是在out文件里面打印hehe但是有两条语句操作不原子就是close(1); dup(fd);如果在dup(fd);之前有其他进程使用了dup()这个函数那么1这个位置将会被占用hehe将会打印到其他文件里面。还有一个问题如果fd本身就是1close(1) 之后fd已经失效又dup(fd)则会出现错误解决方法使用dup2函数----原子操作关闭与重定向一起操作。dup2(fd,1) 这条语句首先会关闭1然后将1作为fd的副本。----保证了原子操作。如果fd1那么这条语句什么也不做并且返回newfd。宏观编程思想不要内存泄漏。不要越界。不要认为自己在写一个main函数永远认为自己在写一个模块。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑