今天学习了一下Linux poll的东西,当然还是看韦老师的视频,但是现在有自己的思路,带着自己的思路跟目的去想,会体会更深。也不知道是不是没看韦老师的新视频,反正觉得老视频里韦老师总是把一些东西带到函数里去一层又一层的剖析,但是毕竟很多看视频的都是初学者,这样子感觉清晰,实际绕晕了很多东西,而且很多函数的调用和一些去找相关类似函数运用的方式感觉没有说出自己的经验,比如Linux里调用irq_request,如果你是一个要用中断的人,你怎么去知道用这个函数,这个函数的相关定义很多,你怎么去知道运用哪个,然后一些相关的例子到底哪些适合我们。这些初学者跟着韦老师做,都没有想过这些问题,确实那些函数,那些参数那么去用没有问题,那些头文件确实存在,但是我们自己去用的时候,怎么去做到这些事情,你能很快的找到它们吗。这里我就想自己去分析分析:
1.我们做字符驱动尽量找相关的
2.尽量找通用文件的linux/xxx asm/xxx
3.尽量找你所用的平台的s3c
4.学会百度
5.去模仿一些内核里别人的驱动,那些驱动无论是稳定度还是说去解读都大有益处
说说今天的poll机制,这个东西是在休眠已经解决了频繁read造成cpu资源的浪费这一问题,但是休眠就意味着除了唤醒的机会出现(写的比较通俗)之前,你都得等在那里,但是像我们如果平时做饭或者下游戏,在游戏下载(唤醒)出现之前我们都不会是一直等待它的到来,我们会做一些自己的事情,同时会时不时的来看一些这个情况,同时游戏下载好了这个唤醒的发生(游戏下载好了)也不一定是我们看见,可以是别人告诉我们,可以是提示的声音,都会让我们知道我们可以退出这种等待状态了(所以有时候poll唤醒相关的文件不只一个,可能上层一个poll,会涉及很多文件(驱动)的op.poll)。所以我首先是从上层开始看,分析上层的poll如何去关联到相关的文件,这个时不时去看一下去观察一下的具体时间是多少,由上层去往底层看。
int poll(struct pollfd *fds, nfds_t nfds, int timeout);
功能:监视并等待多个文件描述符的属性变化(别人给的一个比较简单的定义,仔细一想就是这么回事)
struct pollfd{
int fd; //文件描述符
short events; //等待的事件
short revents; //实际发生的事件
};
revents:revents 域是文件描述符的操作结果事件,内核在调用返回时设置这个域。events 域中请求的任何事件都可能在 revents 域中返回.内核poll中返回给用户空间的
注意:每个结构体的 events 域是由用户来设置,告诉内核我们关注的是什么,而 revents 域是返回时内核设置的,以说明对该描述符发生了什么事件 测试文件中上层用户设置的
poll() 返回结构体中 revents 域不为 0 的文件描述符个数;如果在超时前没有任何事件发生,poll()返回 0;
nfds:用来指定第一个参数数组元素个数
timeout:指定等待的毫秒数,无论 I/O 是否准备好,poll() 都会返回.
我这里只粘贴自己觉得比较简单重要的,
https://blog.csdn.net/skypeng57/article/details/82743681
给出原帖
int main(int argc, char **argv)
{
int fd;
unsigned char key_val;
int ret;
struct pollfd fds[1];
fd = open("/dev/buttons", O_RDWR);
if (fd < 0)
{
printf("can't open!\n");
}
fds[0].fd = fd;
fds[0].events = POLLIN;
while (1)
{
ret = poll(fds, 1, 5000);
if (ret == 0)
{
printf("time out\n");
}
else
{
read(fd, &key_val, 1);
printf("key_val = 0x%x\n", key_val);
}
}
return 0;
}
这样子再去看韦老师的例子就明白了,果然这跟我们分析的一样,fd去绑定具体文件,events描述我们关注的事情,以至于后面连接到它的op,op.poll,相关文件的个数,还有timeout的时间,,因为我们传入的是结构体的地址,所以最后poll() 返回结构体中 revents 域不为 0 的文件描述符个数;
这样子在底层驱动poll中
poll_wait(file, &button_waitq, wait); > 实际效果:执行__pollwait(file, &button_waitq, wait),也就是将 进程挂接到button_waitq等待队列下
,
循环查询相关文件的底层驱动的poll()根据底层驱动的poll的返回值不为0做相关的事件返回(或者timeout时间到)跳出相关队列
for (; pfd != pfd_end; pfd++) { /* 可以监测多个驱动设备所产生的事件 */
pollfd->revents = mask; /* 将实际事件类型返回 */ //mask又是我们自己在底层驱动poll中去赋值
if (count || timed_out) /* 如果有事件发生,或者超时,则跳出poll */ //count 在查询一个文件的mask不为0则++ break; if (!poll_schedule_timeout(wait, TASK_INTERRUPTIBLE, to, slack)) /* 如果没有事件发生,那么陷入休眠状态 */ timed_out = 1; }
个人见解结合网上资料,自己总结给自己看的