一、文件描述符

PCB进程控制块:本质是结构体,成员是文件描述符表,里面有文件描述符0/1/2/…/1023,一个进程默认打开文件的最大数是1024,取用的时候用表中可用的最小的,
其中
0——STDIN_FILENO
1——STDOUT_FILENO
2——STDERR_FILENO
在这里插入图片描述平时返回的fd就是0123这些数(相当于索引下标,就是文件描述符),内容是一个个的指针,指针指向一个个的文件结构体struct file{…},指向的文件就是成功打开的文件

二、阻塞/非阻塞

1,阻塞是谁的属性:是设备文件、网络文件的属性(读常规文件无阻塞概念)
2,所以如果是文件属性的话,是可以改变的(0_NONBLOCK),可以在文件打开的时候(open)再加上(改变)文件属性
3,如果将文件设置成非阻塞,即便发现内容为空,也不会阻塞等待而是会直接返回,但是由于没有内容因此只能返回一个特殊数字-1,(数字0代表读到文件末尾),大于0就表示读到内容了

#include<errno.h>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main()
{
	char buf[10];
	int fd,n;
	//重新打开文件
	fd = open("/dev/tty",0_RDONLY|0_NONBLOCK)//读设备文件设为非阻塞状态,默认是阻塞状态
	if(fd <0)//打开失败
	{
		perror("open /dev/tty");
		exit(1);
	}
tryagain:
	n = read(fd, buf,10);//读fd句柄的文件
	if(n<0)//不能直接返回错误,有可能是非阻塞,跟返回错误号有关系
	{
		if(errno!=EAGAIN)//就是读失败了
		{
			perror("read /dev/tty");
			exit(1);
		}else{//是非阻塞文件,读成功但是没有内容
			write(STDOUT_FILENO,"try again\n",strlen("try again\n"));
			sleep(2);
			goto tryagain;//正常情况都是会在这个基础上设置一个超时,用循环实现xX
		}
	}
	//n>0,就是读到数了
	write(STDOUT_FILENO, buf, n);
	close(fd);//别忘记关闭文件
	return 0;
}

read函数返回-1,并且errno=EAGAIN 或EWOULDBLOCK,说明不是read失败,而是read在以非阻塞方式读一个设备文件(网络文件),并且文件无数据

三、fcntl改文件属性

  • fcntl函数
    改变一个已经打开的文件的访问控制属性,不需要重新打开
    是一个非常复杂的函数,重点掌握两个参数:F_GETFL 和 F_SETFL分别是获取文件状态和设置文件状态,函数有一个返回值即此处的flags

1,F_GETFL 和 F_SETFL 👇代码示例,用于改变文件属性
(上面代码的基础上改
在这里插入图片描述
flags=-1就表示函数获取失败进行报错,如果读成功不管之前文件是否设置非阻塞,都进行或操作,falgs |= 0_NONBLOCK;就可以设置为非阻塞了,涉及到位图的知识,然后再用 F_SETFL参数设置回去
此处位图简单一览:
在这里插入图片描述

Logo

更多推荐