2440 异步通知的代码的实现

本文详细介绍了在2440开发板上实现异步通知IO的驱动程序代码,包括如何绑定中断、请求中断以及发送SIGIO信号进行异步通知。同时,提供了测试程序代码,演示了如何通过设置信号处理机制、获取设备状态以及启用异步通知模式来验证驱动程序的功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在2440开发板上面实现了 异步通知IO的。其中发送的信号必须是SIGIO,否则发送过程会出错。下面的驱动的代码。

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/irq.h>
#include <asm/uaccess.h>
#include <asm/irq.h>
#include <asm/io.h>
#include <asm/arch/regs-gpio.h>
#include <asm/hardware.h>
#include <linux/poll.h>

static struct class *fivedrv_class;
static struct class_device	*fivedrv_class_dev;

struct fasync_struct *async_queue;


static irqreturn_t buttons_irq(int irq, void *dev_id)
{
	/*&async_queue这个结构体绑定了向谁发和这个函数fasync_helper一起*/
	/*这里是异步的IO 所以应该是SIGIO*/
	kill_fasync(&async_queue, SIGIO, POLL_IN);  /* POLL_IN代表这个信号可读POLL_OUT代表这个信号可读*/
	return IRQ_RETVAL(IRQ_HANDLED);
}

static int five_drv_open(struct inode *inode, struct file *file)
{
	request_irq(IRQ_EINT0,  buttons_irq, IRQT_BOTHEDGE, "S2", 1);
	request_irq(IRQ_EINT2,  buttons_irq, IRQT_BOTHEDGE, "S3", 2);
	request_irq(IRQ_EINT11, buttons_irq, IRQT_BOTHEDGE, "S4", 3);
	request_irq(IRQ_EINT19, buttons_irq, IRQT_BOTHEDGE, "S5", 4);	

	return 0;
}

ssize_t five_drv_read(struct file *file, char __user *buf, size_t size, loff_t *ppos)
{

	return 1;
}


int five_drv_close(struct inode *inode, struct file *file)
{
	free_irq(IRQ_EINT0,1);
	free_irq(IRQ_EINT2, 2);
	free_irq(IRQ_EINT11, 3);
	free_irq(IRQ_EINT19, 4);
	return 0;
}


static int five_drv_fasync(int fd,struct file *filp ,int hehe)/*mode on*/
{
	printk("this is fasync \n");
	return fasync_helper(fd,  filp,  hehe, &async_queue);   /*谁调用fasync_helper 函数就向哪个进程发送信号*/

}



static struct file_operations five_drv_fops = {
    .owner   =  THIS_MODULE,    /* 这是一个宏,推向编译模块时自动创建的__this_module变量 */
    .open    =  five_drv_open,     
	.read	 =	five_drv_read,	   
	.release =  five_drv_close,
	.fasync = five_drv_fasync,
};


int major;
static int five_drv_init(void)
{
	major = register_chrdev(0, "five_drv", &five_drv_fops);

	fivedrv_class = class_create(THIS_MODULE, "five_drv");

	fivedrv_class_dev = class_device_create(fivedrv_class, NULL, MKDEV(major, 0), NULL, "key"); /* /dev/buttons */

	return 0;
}

static void five_drv_exit(void)
{
	unregister_chrdev(major, "five_drv");
	class_device_unregister(fivedrv_class_dev);
	class_destroy(fivedrv_class);
	return 0;
}


module_init(five_drv_init);

module_exit(five_drv_exit);

MODULE_LICENSE("GPL");

下面的是测试程序方面的代码段

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <poll.h>
#include <signal.h>
#include <unistd.h>
#include <fcntl.h>

void func(signo)
{
	printf("this is no.%d \n",signo);

}
int main(int argc, char **argv)
{
	int fd;
	int flags;

	fd= open("/dev/key", O_RDWR);

	if (fd<0)
	{
		printf("can't open!\n");
	}
	/*启动信号机制*/
	signal(SIGIO,func);/*让func来处理这个sigio信号*/
	fcntl(fd,F_SETOWN,getpid());  /*告诉设备信号发给当前进程*/
	flags =fcntl(fd,F_GETFL);       /*获取设备当前状态*/
	/*每当FASYNC标志改变的时候,驱动程序中的fasync()函数得以执行*/
	fcntl(fd,F_SETFL,flags | FASYNC);  /*使支持FASYNC 即异步通知模式*/
     /*谁调用fasync_helper 函数就向哪个进程发送信号*/
	while (1)
	{
		sleep(10000);
	}
	return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值