您的位置:首页 > 其它

高级字符驱动程序操作之异步通知IO(实践篇)基于内核2.6.35-30

2012-03-21 08:58 591 查看
async.c 主要展示异步通知机制在驱动程序中的实现

[plain]
view plaincopyprint?

#include <linux/module.h>
#include <linux/init.h>

#include <linux/fs.h> /* everything... */
#include <linux/types.h> /* size_t */
#include <linux/cdev.h>
#include <linux/fcntl.h>
#include <asm/uaccess.h> /* copy user */
#include <linux/poll.h> /* POLL_IN */

#include <linux/sched.h>
#include <linux/slab.h>

MODULE_AUTHOR("victorsummer");
MODULE_LICENSE("Dual BSD/GPL");

static int async_major = 0;
struct fasync_struct *async_queue;
static char *buffer = NULL;

ssize_t async_read (struct file *filp, char __user *buf, size_t count, loff_t *pos)
{
if(buffer)
copy_to_user(buf, buffer, count);

return count;
}

ssize_t async_write (struct file *filp, const char __user *buf, size_t count,
loff_t *pos)
{
if(buffer)
copy_from_user(buffer, buf, count);
if(async_queue)
kill_fasync(&async_queue, SIGIO, POLL_IN);
return count;
}

static int async_fasync(int fd, struct file *filp, int mode)
{
return fasync_helper(fd, filp, mode, &async_queue);
}

int async_release(struct inode *inode, struct file *filp)
{
async_fasync(-1, filp, 0);
return 0;
}

static int async_open(struct inode *inode, struct file *filp)
{
return nonseekable_open(inode, filp);
}

struct file_operations async_fops = {
.owner = THIS_MODULE,
.read = async_read,
.write = async_write,
.fasync = async_fasync,
.release = async_release,
.open = async_open,
};

int async_init(void)
{
int result;
dev_t dev = 0;

struct cdev *async_cdev = cdev_alloc();

if (async_major) {
dev = MKDEV(async_major, 0);
result = register_chrdev_region(dev, 1, "async");
} else {
result = alloc_chrdev_region(&dev, 0, 1, "async");
async_major = MAJOR(dev);
}
if (result < 0) {
return result;
}

if(!buffer)
buffer = kmalloc(1024*sizeof(char), GFP_KERNEL);

cdev_init(async_cdev, &async_fops);
async_cdev->owner = THIS_MODULE;
cdev_add(async_cdev, dev, 1);

return 0;
}

void async_cleanup(void)
{
dev_t devno;
if(buffer)
{
kfree(buffer);
buffer = NULL;
}
devno = MKDEV(async_major, 0);
unregister_chrdev_region(devno, 1);
}

module_init(async_init);
module_exit(async_cleanup);

[plain]
view plaincopyprint?

KERNELDIR = /usr/src/linux-headers-2.6.35-30-generic

PWD := $(shell pwd)

obj-m := async.o

modules:
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules

KERNELDIR = /usr/src/linux-headers-2.6.35-30-generic
PWD := $(shell pwd)

obj-m := async.o

modules:
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules
3. async_testr.c 异步读取程序

[plain]
view plaincopyprint?

#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>
#include <signal.h>
#include <string.h>

int async_fd;
void sig_handler(int signo)
{
int code;

if (signo==SIGIO)
{
char *buf = malloc(30*sizeof(char));

if ((code=read(async_fd, buf, 24)) == -1)
printf("read err! code=%d /n", code);

else
printf("read ok! code=%d /n", code);
printf("Read %s from async module /n", buf);

free(buf);
}
return;
}

int main()
{
struct sigaction action;

memset(&action, 0, sizeof(action));
action.sa_handler = sig_handler;
action.sa_flags = 0;

sigaction(SIGIO, &action, NULL);

async_fd = open("/dev/async", O_RDONLY);
fcntl(async_fd, F_SETOWN, getpid());
fcntl(async_fd, F_SETFL, fcntl(STDIN_FILENO, F_GETFL) | FASYNC);

while(1)
{
sleep(86400);
}

close(async_fd);
exit(0);
}

[plain]
view plaincopyprint?

#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>

int main()
{
char *write_buffer = "Hello, Character driver!";

int async_fd;

int code;

async_fd = open("/dev/async",O_WRONLY );

while(*write_buffer != '\0')
{
code = write(async_fd , write_buffer , 24);

printf("Write %d bytes to async_fd/n", code);
write_buffer += code;
}

close(async_fd);

exit(0);
}

#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>

int main()
{
char *write_buffer = "Hello, Character driver!";

int async_fd;

int code;

async_fd = open("/dev/async",O_WRONLY );

while(*write_buffer != '\0')
{
code = write(async_fd , write_buffer , 24);
printf("Write %d bytes to async_fd/n", code);
write_buffer += code;
}

close(async_fd);

exit(0);
}
5. Makefile

[plain]
view plaincopyprint?

all : async_testw.o async_testr.o
gcc -o async_testw.o async_testw.c
gcc -o async_testr.o async_testr.c

all : async_testw.o async_testr.o
gcc -o async_testw.o async_testw.c
gcc -o async_testr.o async_testr.c

6. 开始测试

装载驱动程序

sudo insmod ./async.ko

查看主设备号,假设为249

cat /proc/devices

建立设备节点

sudo mknod /dev/async c 249 0

更改权限

sudo chgrp staff /dev/async

sudo chmod 664 /dev/async

在终端1中打开异步读取程序,程序开始sleep

sudo ./async_testr.o

在终端2中打开写入程序

sudo ./async_testw.o

结果:

终端2打印:

Write 24 bytes to async_fd

终端1打印:

read ok! code=24

Read Hello, Character driver! from async module
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐