linux 串口 多路复用,Linux多路复用Select()与poll()函数

e20ed7dacce57cd89a537f7cc9131983.png

▲长按图片保存可分享至朋友圈

微信公众号:嵌入式开发圈

关注可了解更多的教程。问题或建议,请公众号留言;

文章学习收集网络相关知识点进行整理,如有侵权,请联系删除。

小编准备写一本有关嵌入式产品方面的书,投票看看大家希望我写啥?如果觉得想法可以增多,欢迎留言区讨论,写写各位圈友的支持!

e1ec2b60463e382502987b4d382c9d18.gif

提出问题

在Linux编程中,一切皆文件,往往是对一个文件进行操作,比如说串口,和传感器打交道,一般情况下就是一来一去,一收一发,但是,如果我有多个传感器,而传感器之间又有关联,我想同时监控一个或者多个以上的文件描述符,要如何去实现这个需求呢?

35d99d1f0e4ac6152abfff886aed70ea.gif

e1ec2b60463e382502987b4d382c9d18.gif

解决问题

Linux健全的API已经为我们提供了解决问题的方法,在此我们引入select()函数、poll函数。

select()和poll()本质上来讲做的是同一件事,只是完成的方法不一样。两者都通过检验一组文件描述符来检测是否有特定的时间将在上面发生并在一定的时间内等待其发生。

[重要事项:无论select()还是poll()都不对普通文件起很大作用,它们着重用

于套接口(socket)、管道(pipe)、伪终端(pty)、终端设备(tty)和其他一些字符设备,但是这些操作都是系统相关(system-dependent)的。]

35d99d1f0e4ac6152abfff886aed70ea.gif

e1ec2b60463e382502987b4d382c9d18.gif

如何使用select函数?

我们先来看看select函数:

头文件包含:

#include /* 根据POSIX.1 - 2001 */

/*根据早期的标准*/

#include

#include

#include

函数参数解析:

参数解析:

readset:    用来检查可读性的一组文件描述符。

writeset:   用来检查可写性的一组文件描述符。

exceptset:  用来检查意外状态的文件描述符。(注:错误并不是意外状态)

timeout:    NULL指针代表无限等待,否则是指向timeval结构的指针,代表最长等待时间。(如果其中tv_sec和

函数将返回响应操作的对应操作文件描述符的总数,且三组数据均在恰当位置被修改,只有响应操作的那一些没有修改。接着应该用FD_ISSET宏来查找返回的文件描述符组。

select()函数的接口主要是建立在一种叫'fd_set'类型的基础上。它('fd_set')是一组文件描述符(fd)的集合。由于fd_set类型的长度在不同平台上不同,因此应该用一组标准的宏定义来处理此类变量:

set;

set);       /* 将set清零 */

set);    /* 将fd加入set */

set);    /* 将fd从set中清除 */

set);  /* 如果fd在set中则真 */

在过去,一个fd_set通常只能包含少于等于32个文件描述符,因为fd_set其实只用了一个int的比特矢量来实现,在大多数情况下,检查fd_set能包括任意值的文件描述符是系统的责任,但确定你的fd_set到底能放多少有时你应该检查/修改宏FD_SETSIZE的值。*这个值是系统相关的*,同时检查你的系统中的select()的man手册。有一些系统对多于1024个文件描述符的支持有问题。

[Linux就是这样的系统!你会发现sizeof(fd_set)的结果是128(*8 =FD_SETSIZE=1024)尽管很少你会遇到这种情况。]

35d99d1f0e4ac6152abfff886aed70ea.gif

e1ec2b60463e382502987b4d382c9d18.gif

测试案例

int isready(int fd){

int rc;

struct timeval tv;

0;

1, &fds, NULL, NULL, &tv);

if (rc 0)

return -1;

return FD_ISSET(fd,&fds) ? 1 : 0;

当然如果我们把NULL指针作为fd_set传入的话,这就表示我们对这种操作的发生不感兴趣,但select()还是会等待直到其发生或者超过等待时间。

[在Linux中,timeout指的是程序在非sleep状态中度过的时间,而不是实际上过去的时间,这就会引起和非Linux平台移植上的时间不等问题。移植问题还包括在System V风格中select()在函数退出前会把timeout设为未定义的NULL状态,而在BSD中则不是这样,Linux在这点上遵从System V,因此在重复利用timeout指针问题上也应该注意。]

35d99d1f0e4ac6152abfff886aed70ea.gif

e1ec2b60463e382502987b4d382c9d18.gif

如何使用poll()函数?

poll函数:

#include

int poll(struct pollfd fds[], nfds_t nfds, int timeout);

poll和select实现功能差不多,但poll效率高,以后要多用poll。poll()接受一个指向结构'struct pollfd'列表的指针,其中包括了你想测试的文件描述符和事件。事件由一个在结构中事件域的比特掩码确定。当前的结构在调用后将被填写并在事件发生后返回。在SVR4(可能更早的一些版本)中的 "poll.h"文件中包含了用于确定事件的一些宏定义。事件的等待时间精确到毫秒 (但令人困惑的是等待时间的类型却是int),当等待时间为0时,poll()函数立即返回,-1则使poll()一直挂起直到一个指定事件发生。下面是pollfd的结构。

struct pollfd

int fd;        /* 文件描述符 */

short events;  /* 等待的事件 */

short revents; /* 实际发生了的事件 */

和select()十分相似,当返回正值时,代表满足响应事件的文件描述符的个数,如果返回0则代表在规定事件内没有事件发生。如发现返回为负则应该立即查看errno,因为这代表有错误发生。

如果没有事件发生,revents会被清空,所以你不必多此一举。

38163dcc61bae19fd96ac05577be7a8d.png

poll函数可用的测试值

38163dcc61bae19fd96ac05577be7a8d.png

3915d622780d52202be77117be4f9256.png

例如:

0].events = POLLIN; /*将测试条件设置成普通或优先级带数据可读*/

然后 :

//这样就可以监听fds里面文件描述符了,当满足特定条件就返回,并将结果保存在revents中。

int pollresult = poll(fds,xx,xx);

e1ec2b60463e382502987b4d382c9d18.gif

poll案例

#include

#include

#include

#include

#include

#include

#include

#include

#define MAX_BUFFER_SIZE 1024

#define IN_FILES 3

#define TIME_DELAY 60*5

#define MAX(a,b) ((a>b)?(a):(b))

int main(int argc ,char **argv){

struct pollfd fds[IN_FILES];

char buf[MAX_BUFFER_SIZE];

int i,res,real_read, maxfd;

0].fd = 0;

if((fds[1].fd=open("data1",O_RDONLY|O_NONBLOCK)) 0)

fprintf(stderr,"open data1 error:%s",strerror(errno));

return 1;

if((fds[2].fd=open("data2",O_RDONLY|O_NONBLOCK)) 0)

fprintf(stderr,"open data2 error:%s",strerror(errno));

return 1;

for (i = 0; i

while(fds[0].events || fds[1].events || fds[2].events)

if (poll(fds, IN_FILES, TIME_DELAY) <= 0)

printf("Poll error\n");

return 1;

for (i = 0; i

if (fds[i].revents)

memset(buf, 0, MAX_BUFFER_SIZE);

if (real_read 0)

if (errno != EAGAIN)

return 1;

else if (!real_read)

0;

else

if (i == 0)

if ((buf[0] == 'q') || (buf[0] == 'Q'))

return 1;

else

'\0';

printf("%s", buf);

exit(0);

35d99d1f0e4ac6152abfff886aed70ea.gif

f7a81b29e38d4426769fbc84f2ef946e.gif

16c75cca54e1a63f51c7cb837e5e20ea.png

91c3b5776209ea67ae8f13ecae1f0392.png

另外推荐相关课程:

韦东山老师优质嵌入式学习干货推荐:包括ARM裸机开发、Linux设备驱动程序、Linux应用程序开发、Android系统学习、Linux设备树等。

在我这里购买韦东山老师的课程还可得到本人的技术支持,手把手带你学习嵌入式!

520fad94aeb986d48642b79ee9a63619.png

47acdefff1c99b65eb592beaf883b7d2.png

王争老师优秀数据结构算法学习课程推荐

  • 0
    点赞
  • 1
    收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
©️2022 CSDN 皮肤主题:1024 设计师:我叫白小胖 返回首页
评论
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值