本文最后更新于333 天前,其中的信息可能已经过时,如有错误请发送邮件到273925452@qq.com

只修改了第三节的按键程序button_test.c LED的程序是第二节的程序
测试环境:
VsCode(远程)+Ubuntu
IMX6ULL_PRO
测试环境:
VsCode(远程)+Ubuntu
IMX6ULL_PRO
POLL机制(闹钟)
POLL
POLL机制是Linux系统中用于实现I/O多路复用的一种方法,允许一个进程同时监控多个文件描述符的I/O状态。与select()相比,poll()没有文件描述符数量的限制,并且提供了更灵活的事件类型支持。POLL机制的核心在于poll()函数,它允许用户指定一个pollfd结构体数组来跟踪多个文件描述符的事件。POLL机制提供了一种非阻塞的方式监控多个I/O通道,适用于需要同时处理多个网络连接或设备的应用场景。
主要涉及的函数
poll() 函数
#include <sys/poll.h>
int poll(struct pollfd *fds, nfds_t nfds, int timeout);
poll() 函数
其中:
struct pollfd *fds 是一个指向pollfd结构体数组的指针,每个元素代表一个需要监控的文件描述符及其事件。
nfds_t nfds 是数组中元素的数量。
int timeout 是一个以毫秒为单位的超时值,如果在该时间内没有任何事件发生,则poll()将返回。
struct pollfd *fds 是一个指向pollfd结构体数组的指针,每个元素代表一个需要监控的文件描述符及其事件。
nfds_t nfds 是数组中元素的数量。
int timeout 是一个以毫秒为单位的超时值,如果在该时间内没有任何事件发生,则poll()将返回。
pollfd 结构体
pollfd结构体定义了每个文件描述符的监控信息:
struct pollfd {
int fd; /* 文件描述符 */
short events; /* 要监控的事件掩码 */
short revents; /* 实际发生的事件掩码 */
};
监控的事件
events成员可以设置以下事件之一或组合:
events成员
– POLLIN:表示文件描述符可读。
– POLLPRI:紧急数据可读(如带外数据)。
– POLLOUT:表示文件描述符可写。
– POLLERR:错误发生。
– POLLHUP:挂起或终止。
– POLLNVAL:无效的请求描述符。
– POLLWRBAND:带外数据可写。
– POLLMSG:消息队列中有数据。
– POLLPRI:紧急数据可读(如带外数据)。
– POLLOUT:表示文件描述符可写。
– POLLERR:错误发生。
– POLLHUP:挂起或终止。
– POLLNVAL:无效的请求描述符。
– POLLWRBAND:带外数据可写。
– POLLMSG:消息队列中有数据。
使用流程
events成员
1.初始化pollfd数组,设置每个pollfd的fd和events字段。
2.调用poll()函数,传入pollfd数组、数组长度和超时时间。
3.poll()函数阻塞直到至少有一个文件描述符准备就绪或超时。
4.检查pollfd数组中的revents字段,确定哪些文件描述符发生了事件。
5.根据事件类型采取相应的操作,如读取数据或写入数据。
2.调用poll()函数,传入pollfd数组、数组长度和超时时间。
3.poll()函数阻塞直到至少有一个文件描述符准备就绪或超时。
4.检查pollfd数组中的revents字段,确定哪些文件描述符发生了事件。
5.根据事件类型采取相应的操作,如读取数据或写入数据。
程序
button_test.c
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <poll.h>
#include <signal.h>
#define LED_DEV "/dev/led"
#define BUTTON_DEV "/dev/100ask_button0"
/*
* ./button_test /dev/100ask_button0
*
*/
int main(int argc, char **argv)
{
int fd,fd1;
char val;
struct pollfd fds[2]; // fds数组用于注册要监控的事件,fds[0]监控fd上的读事件(POLLIN),fds[1]监控fd1上的写事件(POLLOUT)。
int ret;
char buf[2];
const int timeout = 1000; // Wait for up to 1 second
/* 1. 判断参数 */
if (argc != 2)
{
printf("Usage: %s <dev>\n", argv[0]);
return -1;
}
/* 2. 打开文件key */
fd = open(BUTTON_DEV, O_RDWR | O_NONBLOCK); //非阻塞(查询)
if (fd == -1)
{
printf("can not open file %s\n", argv[1]);
return -1;
}
/* 3. 读文件 */
if (read(fd, &val, 1) != 1)
{
printf("read error %s\n", argv[1]);
close(fd);
return -1;
}
printf("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);
fd1 = open(LED_DEV, O_RDWR);
if (fd1 == -1)
{
perror("can not open LED device");
close(fd);
return -1;
}
printf("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);
/* Setup poll descriptors */
fds[0].fd = fd;
fds[0].events = POLLIN;
fds[1].fd = fd1;
fds[1].events = POLLOUT;
/* Main loop */
buf[0] = 0;
while (1)
{
if(poll(fds, 2, -1) == -1)
{
perror("poll error");
break;
}
/* Check if button has data available */
if (fds[0].revents & POLLIN) // fds[0]上的读事件发生,说明按钮有数据可用
{
if (read(fd, &val, 1) != 1) // 读取按钮的状态到val变量中
{
perror("read error");
break;
}
/* Control LED based on button state */
if (val == 0)
{
buf[1] = 0;
ret = write(fd1, buf, 2);
}
else if (val == 1)
{
buf[1] = 1;
ret = write(fd1, buf, 2);
}
else
{
fprintf(stderr, "Unknown button state: %c\n", val);
}
if (ret != 2)
{
perror("write error");
break;
}
printf("get button : %d\n", val);
usleep(timeout); // Sleep for 500 milliseconds
}
}
/* 清理 */
close(fd);
close(fd1);
return 0;
}
上机
安装LED,KEY驱动
执行程序
./button_test /dev/100ask_button0
测试成功
按着按键控制灯亮,松开灯灭
修改程序控制亮灭方式
按下亮,在按一下灭
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <poll.h>
#include <signal.h>
#define LED_DEV "/dev/led"
#define BUTTON_DEV "/dev/100ask_button0"
/*
* ./button_test /dev/100ask_button0
*
*/
int main(int argc, char **argv)
{
int fd,fd1;
char val;
struct pollfd fds[2]; // fds数组用于注册要监控的事件,fds[0]监控fd上的读事件(POLLIN),fds[1]监控fd1上的写事件(POLLOUT)。
int ret;
char buf[2];
const int timeout = 100000;
int led_state = 0;
/* 1. 判断参数 */
if (argc != 2)
{
printf("Usage: %s <dev>\n", argv[0]);
return -1;
}
/* 2. 打开文件key */
fd = open(BUTTON_DEV, O_RDWR | O_NONBLOCK); //非阻塞(查询)
if (fd == -1)
{
printf("can not open file %s\n", argv[1]);
return -1;
}
/* 3. 读文件 */
if (read(fd, &val, 1) != 1)
{
printf("read error %s\n", argv[1]);
close(fd);
return -1;
}
printf("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);
fd1 = open(LED_DEV, O_RDWR);
if (fd1 == -1)
{
perror("can not open LED device");
close(fd);
return -1;
}
printf("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);
/* Setup poll descriptors */
fds[0].fd = fd;
fds[0].events = POLLIN;
fds[1].fd = fd1;
fds[1].events = POLLOUT;
/* Main loop */
buf[0] = 0;
while (1)
{
if(poll(fds, 2, -1) == -1)
{
perror("poll error");
break;
}
/* Check if button has data available */
if (fds[0].revents & POLLIN) // fds[0]上的读事件发生,说明按钮有数据可用
{
if (read(fd, &val, 1) != 1) // 读取按钮的状态到val变量中
{
perror("read error");
break;
}
/* Control LED based on button state */
if (val == 0)
{
led_state ^= 0x01;
}
if (led_state == 0)
{
buf[1] = 0;
ret = write(fd1, buf, 2);
}
else if (led_state == 1)
{
buf[1] = 1;
ret = write(fd1, buf, 2);
}
else
{
fprintf(stderr, "Unknown button state: %c\n", val);
}
if (ret != 2)
{
perror("write error");
break;
}
printf("get button : %d\n", val);
usleep(timeout); // Sleep for 500 milliseconds
}
}
/* 清理 */
close(fd);
close(fd1);
return 0;
}
评论