linux应用与驱动之间的通讯--应用篇

linux应用访问驱动的4种方式

1.非阻塞

与阻塞方式相反,在应用获取驱动返回的数据时,不管此时驱动有没有数据,都立即返回
在应用程序中 ,APP调用open函数时,传入“O_NONBLOCK”表示“非阻塞”

//头文件
       #include <sys/types.h>
       #include <sys/stat.h>
       #include <fcntl.h>
//函数原型: int open(const char *pathname, int flags);
//例子:
 fd= open(file, O_RDWR | O_NONBLOCK);

2.阻塞方式

与非阻塞方式相反,在应用获取驱动返回的数据时,有数据立即返回,无数据则休眠,等到数据到来,将其唤醒

//头文件
       #include <sys/types.h>
       #include <sys/stat.h>
       #include <fcntl.h>
//函数原型: int open(const char *pathname, int flags);
//例子:
fd = open(file, O_RDWR);

3.POLL/SELECT方式方式

POLL机制、SELECT机制是完全一样的,只是APP接口函数不一样。

//头文件
 #include <poll.h>
  //函数原型:int poll(struct pollfd *fds, nfds_t nfds, int timeout);
  //其中 struct pollfd结构体
   struct pollfd {
               int   fd;         /* 文件描述 */
               short events;     /* 设置我们希望发生的事件 */
               short revents;    /* 实际发生的事件 */
           };
         
  nfds_t  调用者应在 nfds 中指定 fds 数组中的项目数。 
  timeout 参数指定 poll() 应该阻塞等待文件描述符准备好的毫秒数。
 调用将阻塞,直到:
  * 文件描述符已经准备好; 
  * 调用被信号处理程序中断;
  * 超时
  
//events; 举例(不全,详细请去参考man poll)
 // POLLIN  有数据要读取
 // POLLPRI 文件描述符有一些异常情况。可能性包括:
  * TCP 套接字上有带外数据
 * 数据包模式下的伪终端主机在从机上看到状态更改
 * 修改了 cgroup.events 文件
 //POLLOUT 现在可以进行写入,
 //例子 
 struct pollfd fds;
 nfds_t nfds = 1;
 		fds.fd = fd;
		fds.events  = POLLIN; //期待输入事件
		fds.revents = 0;
		ret = poll(fds, nfds, 5000);

SELECT机制

//头文件
     #include <sys/select.h>
       #include <sys/time.h>
       #include <sys/types.h>
       #include <unistd.h>

  //函数原型: int select(int nfds, fd_set *readfds, fd_set *writefds,
                  fd_set *exceptfds, struct timeval *timeout);
   //fd_set使用下列函数配置
       void FD_CLR(int fd, fd_set *set);
       int  FD_ISSET(int fd, fd_set *set);
       void FD_SET(int fd, fd_set *set);
       void FD_ZERO(fd_set *set);

提供了四个宏来操作集合。 FD_ZERO() 清除一组。 FD_SET() 和 FD_CLR() 分别从集合中添加和删除给定的文件描述符。 FD_ISSET() 测试文件描述符是否是集合的一部分
//nfds 应设置为三个集合中任何一个中编号最高的文件描述符,加 1
//    timeout
 struct timeval {
               long    tv_sec;         /* seconds */
               long    tv_usec;        /* microseconds */
           };
 struct timespec {
               long    tv_sec;         /* seconds */
               long    tv_nsec;        /* nanoseconds */
           };


//例子
	int nfds;
	struct timeval tv;
	fd_set readfds;
/* 设置超时时间 */
		tv.tv_sec  = 5;
		tv.tv_usec = 0;
		
		/* 想监测哪些文件? */
		FD_ZERO(&readfds);    /* 全部清零 */	
		FD_SET(fd, &readfds); /* 想监测fd */
         nfds = fd + 1; /* nfds 是最大的文件句柄+1, 注意: 不是文件个数, 与poll不一样 */ 
		ret = select(nfds, &readfds, NULL, NULL, &tv);

4.异步通知

所谓异步通知,就是APP处理自身的事情,当驱动程序有数据时它会主动给APP发信号

#include <signal.h>
//signal() 将信号符号的处置设置为处理程序,它可以是 SIG_IGN、SIG_DFL 或程序员定义的函数(“信号处理程序”)的地址。
如果将信号signum 传递给进程,则会发生以下情况之一:
 * 如果处置设置为SIG_IGN,则忽略该信号。
 * 如果处置设置为 SIG_DFL,则发生与信号关联的默认操作。
 * 如果处置设置为函数,则首先处置被重置为 SIG_DFL,或者信号被阻塞,然后使用参数 signum 调用处理程序。如果处理程序的调用导致信号被阻塞,则信号在从处理程序返回时被解除阻塞。
注意:信号 SIGKILL 和 SIGSTOP 不能被捕获或忽略。

例子:
① 编写信号处理函数:
static void sig_func(int sig)
{
	int val;
	read(fd, &val, 4);
	printf("get value : 0x%x\n", val);
}
② 注册信号处理函数:
signal(SIGIO, sig_func);
③ 打开驱动:
fd = open(file, O_RDWR);
④ 把进程ID告诉驱动
fcntl(fd, F_SETOWN, getpid());
⑤ 使能驱动的FASYNC功能:
flags = fcntl(fd, F_GETFL);
fcntl(fd, F_SETFL, flags | FASYNC);


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值