Aprendizaje de Drive-notas diarias day6

[1] Multiplexación IO Multiplexación
IO: En la misma aplicación de aplicación, si desea monitorear múltiples descriptores de archivos al mismo tiempo,
use select, poll, epoll para monitorear, si los datos no están listos, seleccione
poll, epoll Bloqueará. Cuando los datos del hardware están listos, se genera una interrupción y se pueden
activar select, poll y epoll en la función de procesamiento de interrupciones del controlador. Cuando se
despiertan, juzgan qué datos de descripción de archivo en el conjunto de descriptores de archivo están listos
. Si los datos están listos, simplemente lea los datos del hardware en el espacio del usuario.

fd1 = open("mma",权限);
fd2 = open("mpu",权限);
将fd1和fd2放入到文件描述符的集合中(读表)
select(maxfd+1,&读表,NULL,NULL,NULL);
if(FD_ISSET(fd1,读表)){
	read(fd1,buf,sizeof(buf));
}
if(FD_ISSET(fd2,读表)){
	read(fd2,buf,sizeof(buf));
	
}
------------------------------------------------
vfs:
	sys_select:
	1.在内核空间分配表的内存,然后调用copy_from_user
	将用户空间的文件描述符表拷贝到内核空间。
	
	2.从文件描述符表中取出文件描述符
		fd1 fd2 fd3
		
		fd1-->fd_array[fd1]--->file--->poll(指针)-->driver1_poll()
		ret1  = driver1_poll();
		
		ret1=0 ret2=0 ret3=0 进程休眠
		在虚拟文件系统层,实现了poll_table结构体
		调用driver1和driver2中的poll,如果得到的结果都是
		0,表示两个驱动的数据都没有准备好,如果数据都没
		准备好就将进程休眠。
	
	3.休眠的进程被驱动的wake_up 唤醒
		当某一个时间点有一个或者多个进程同时调用wake_up
		唤醒了这个休眠的进程。然后它会重新全部调用一下
		驱动中的poll函数,获取到返回值,
		fd1 fd2 fd3
		
		fd1-->fd_array[fd1]--->file--->poll(指针)-->driver1_poll()
		ret1  = driver1_poll();
		
		ret1=POLLIN ret2=0 ret3=POLLIN 
		
		将ret1 ret3对应的文件描述符找到fd1 fd3,
		并将fd1 fd3放到文件描述符表中
		
	4.将文件描述符表返回到用户空间copy_to_user。
-------------------------------------------------
驱动:
	  driver1             driver2
	driver1_open         driver2_open
	dirver1_poll         dirver2_poll
	driver1_read         driver2_read
	
	wake_up              wake_up
	
unsigned int (*poll) (struct file *, struct poll_table_struct *);
	
grep ".poll = " * -nR
//搜索内核中已经实现的poll函数,通过内核实现的poll函数
//来完成自己的poll函数
	
通过上述代码参考知道,在poll函数中实现的步骤如下
	1.定义mask=0
	
	2.调用poll_wait,不会阻塞,它只是完成等待队列头的提交
	
	3.当条件为真设置mask
		if(condition == 1){
			mask = POLLIN/POLLOUT;
		}
		
	4.返回mask

[2] Uso de epoll:
#include <sys / epoll.h>

 int epoll_create(int size);
 功能:创建一个epoll的实例
 参数:
	@size:已经不再使用,可以填写任意值
 返回值:成功返回epoll的文件描述符,失败返回-1;
 
 int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);
 功能:控制箱epfd中添加、修改、删除本次要监听的事件的类型
 参数:
	@epfd:epoll的文件描述符
	@op  :EPOLL_CTL_ADD 添加事件
		  EPOLL_CTL_MOD 修改事件 
		  EPOLL_CTL_DEL 删除事件
	@fd  :文件描述符
	@event:事件的结构体对象
	    struct epoll_event {
           uint32_t     events; //EPOLLIN EPOLLOUT
           epoll_data_t data;        /* User data variable */
       };

 返回值:成功返回0,失败返回-1
  
 int epoll_wait(int epfd, struct epoll_event *revents,
                  int maxevents, int timeout);
 功能:完成阻塞,如果有数据准备好,就返回
 参数:
	@epfd     :epoll的文件描述符
	@revents  :返回的事件结构体
	@maxevents:最大的结构体个数
	@timeout  :超时时间
返回值:1.成功返回准备好的文件描述符的个数
		2.超时返回0
		3.失败返回-1;

[3] Pregunta de la entrevista: ¿Cuál es la diferencia entre select / poll / epoll?
select:
1. El descriptor de archivo más grande que seleccionan los monitores es 1024.
2. Select borrará la tabla de descriptores de archivos cada vez, y cada vez que necesite copiar la tabla de espacio de usuario en el espacio del kernel, la eficiencia es baja.
3. Una vez que se activa la selección, debe reiniciarse. Al sondear la función de encuesta del conductor una vez, la eficiencia es relativamente baja

poll:
1.poll监听的最大的文件描述符没有个数限制
2.poll不需要重新构造文件描述符表,只需要从用户空间向内核空间拷贝一次数据即可
3.poll被唤醒之后需要重新轮询一遍驱动的poll函数,效率比较低

epoll:(本世纪最好用的io多路复用机制)
1.epoll监听的最大的文件描述符没有个数限制
2.epoll不需要重新构造文件描述符表,只需要从用户空间向内核空间拷贝一次数据即可
3.epoll被唤醒之后epoll直接能拿到唤醒的文件描述符,将文件描述符拷贝到用户空间即可
  不需要轮询,效率高。

[4] Notificación asincrónica
Cuando los datos del hardware no están listos, la aplicación se puede ejecutar libremente.
Cuando los datos están listos, el hardware enviará una interrupción,
el controlador de interrupciones envía una señal a la aplicación, cuando una aplicación
cuando la señal recibida, realiza la función de procesamiento de señal, la función de procesamiento de señal
en Solo lee los datos.

user:
	1.注册信号处理函数
		signal(SIGIO,信号处理函数);
	2.调用驱动的fasync函数
		unsigned int flags = fcntl(fd,F_GETFL);
		fcntl(fd,F_SETFL,flags|FASYNC);
	3.指定接收信号的进程
		fcntl(fd,F_SETOWN,getpid());  
------------------------------------------------------
VFS:
	sys_fcntl:
		 err = do_fcntl(fd, cmd, arg, filp);
			switch(cmd)
			case F_SETFL:
			  err = setfl(fd, filp, arg);
			    if (((arg ^ filp->f_flags) & FASYNC) && filp->f_op &&                                          
				filp->f_op->fasync) {
				error = filp->f_op->fasync(fd, filp, (arg & FASYNC) != 0); 

------------------------------------------------------
kernel:fops: .fasync = driver_fasync;
	  driver_fasync();
	1.实现驱动的fasync函数
		grep ".fasync =" * -nR
		struct fasync_struct *fapp;
		int fasync_helper(int fd, struct file * filp, 
			int on, struct fasync_struct **fapp)
		功能:初始异步通知结构体,并把异步通知结构体放入队列。
		

	2. 实现发送信号的过程
		 kill_fasync(&fapp, SIGIO, POLL_IN);

Supongo que te gusta

Origin blog.csdn.net/weixin_48430195/article/details/108671820
Recomendado
Clasificación