歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux基礎 >> Linux技術 >> linux 驅動函數簡介

linux 驅動函數簡介

日期:2017/3/3 12:50:24   编辑:Linux技術

1)在驅動中使用 DECLARE_WAIT_QUEUE_HEAD ;進程加入等待隊列

a.增加頭文件 #include <linux/sched.h>

b.定義以下變量

①.static DECLARE_WAIT_QUEUE_HEAD(gk_modules_wait_event);

②.static volatile int gk_modules_wait_event_flag = 0;

c.在函數A中調用以下函數,若 gk_modules_wait_event_flag = 0; 函數A進入休眠

①.wait_event_interruptible(gk_modules_wait_event, gk_modules_wait_event_flag);

d.在中斷函數B或其他函數B運行時;先置 gk_modules_wait_event_flag = 1; 再調用以下函數就能喚醒函數A

①.wake_up_interruptible(&gk_modules_wait_event);

2)在驅動中使用 poll 機制

備注: Poll機制會判斷fds中的文件是否可讀,如果可讀則會立即返回,

返回的值就是可讀fd的數量,如果不可讀,那麼就進程就會休眠timeout 這麼長的時間,

然後再來判斷是否有文件可讀,如果有,返回fd的數量,如果沒有,則返回0.

返回表示是否能對設備進行無阻塞可讀或可寫訪問的掩碼;

位掩碼:POLLRDNORM, POLLIN,POLLOUT,POLLWRNORM

設備可讀,通常返回:(POLLIN | POLLRDNORM)

設備可寫,通常返回:(POLLOUT | POLLWRNORM)

a.在驅動中定義以下函數;

若poll指向的函數返回當前可否讀寫的信息。

如果當前可讀寫,返回讀寫信息。

如果當前不可讀寫,則阻塞進程,並等待驅動程序喚醒,重新調用poll函數,或超時返回。

若gk_modules_wait_event_flag為1,則返回文件可讀,若為0則返回0,文件不可讀

static unsigned int  gk_modules_dev_poll(struct file *file, poll_table *wait)
{
	unsigned int mask = 0;

	poll_wait(file, &gk_modules_wait_event, wait); 	<span >	</span>/*<span >	</span>不會立即休眠<span >	</span>*/
	if (gk_modules_wait_event_flag)
		mask |= POLLIN | POLLRDNORM;
	return mask;
}
b.在驅動測試程序中包含#include <poll.h>

struct pollfd fds[1];
fds[0].fd     = fd;
fds[0].events = POLLIN;
ret = poll(fds, 1, 10000);
if (ret == 0)
{
	printf("time out\n");
}
else
{
	/*	用戶程序	*/
}
3)在驅動中異步通知fasync

a.在驅動中定義以下函數,驅動需要知道信號量發給誰

#include <linux/poll.h>
static struct fasync_struct *gk_modules_async;
static int gk_modules_dev_fasync (int fd, struct file *filp, int on)
{
	return fasync_helper (fd, filp, on, &gk_modules_async);
}
b.驅動中發送信號量

kill_fasync(&gk_modules_async,SIGIO,POLL_IN);
c.應用程序中定義,當驅動中調用發送信號量函數時,my_signal_fun(),函數被調用
<span >#include <fcntl.h></span>

void my_signal_fun(void)
{	
	printf("call my_signal_fun\n");
}
int main(int argc, char **argv)
{
	int 	Oflags;

	fd = open("/dev/gk_modules", 2);  			/* 打開設備*/
	signal(SIGIO, my_signal_fun);
	fcntl(fd, F_SETOWN, getpid());
	Oflags = fcntl(fd, F_GETFL); 
	fcntl(fd, F_SETFL, Oflags | FASYNC);
	while(1){
		sleep(2);
	}
}

Copyright © Linux教程網 All Rights Reserved