linux 驱动开发基础,Linux驱动开发基础代码

//fifo.c

//先进先出队列

#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include

#define DEVNAME "GLOBAL_FIFO_DEV"//驱动名称

#define SIZE 2000//缓冲区大小

int major;//主设备号

//设备结构体

struct FIFO_DEV

{

struct cdev cdev;//字符设备结构体

unsigned int current_len;//当前缓冲区中字节数

unsigned char mem[SIZE];//内存缓冲区

struct semaphore sem;//信号量

wait_queue_head_t r_wait;//读等待队列头

wait_queue_head_t w_wait;//写等待队列头

struct fasync_struct *async_queue;//异步结构体指针

};

struct FIFO_DEV *fifo_dev;

//异步通知函数

static int fifo_fasync(int fd,struct file *filp,int mode)

{

struct FIFO_DEV *fifo_dev=filp->private_data;

return fasync_helper(fd,filp,mode,&fifo_dev->async_queue);

}

static int fifo_open(struct inode *inode,struct file *filp)

{

filp->private_data=fifo_dev;

return 0;

}

static int fifo_release(struct inode *inode,struct file *filp)

{

struct FIFO_DEV *fifo_dev=filp->private_data;

fifo_fasync(-1, filp, 0);//将文件从异步操作中删除

return 0;

}

static ssize_t fifo_read(struct file *filp,char __user *buf,size_t count,loff_t *ppos )

{

int ret=0;

struct FIFO_DEV *fifo_dev=filp->private_data;

DECLARE_WAITQUEUE(wait,current);//定义等待队列

down(&fifo_dev->sem);//获取信息量

add_wait_queue(&fifo_dev->r_wait,&wait);//将等待队列加入写等待队列头

if(fifo_dev->current_len==0)

{

if(filp->f_flags &O_NONBLOCK)

{

ret=-EAGAIN;

goto out;

}

else

{

__set_current_state(TASK_INTERRUPTIBLE);//阻塞当前进程

up(&fifo_dev->sem);//释放信息量

schedule();//调度其它进程

if(signal_pending(current))

{

ret=-ERESTARTSYS;

goto out2;

}

down(&fifo_dev->sem);

}

}

if(count>fifo_dev->current_len)

{

count=fifo_dev->current_len;

}

if(copy_to_user(buf,fifo_dev->mem,count))//读取数据到用户缓冲区

{

ret= -EFAULT;

goto out;

}

else

{

memcpy(fifo_dev->mem,fifo_dev->mem+count,fifo_dev->current_len-count);//数据提前

fifo_dev->current_len-=count;

wake_up_interruptible(&fifo_dev->w_wait);//唤醒写等待队列

ret=count;

}

out:up(&fifo_dev->sem);

out2:remove_wait_queue(&fifo_dev->r_wait,&wait);

set_current_state(TASK_RUNNING);

return ret;

}

static ssize_t fifo_write(struct file *filp,char __user *buf,size_t count,loff_t *ppos )

{

int ret;

struct FIFO_DEV *fifo_dev=filp->private_data;

DECLARE_WAITQUEUE(wait,current);

down(&fifo_dev->sem);

add_wait_queue(&fifo_dev->w_wait,&wait);

if(fifo_dev->current_len==SIZE)

{

if(filp->f_flags &O_NONBLOCK)

{

ret=-EAGAIN;

goto out;

}

else

{

__set_current_state(TASK_INTERRUPTIBLE);

up(&fifo_dev->sem);

schedule();

if(signal_pending(current))

{

ret=-ERESTARTSYS;

goto out2;

}

down(&fifo_dev->sem);

}

}

if(count>SIZE-fifo_dev->current_len)

{

count=SIZE-fifo_dev->current_len;

}

if(copy_from_user(fifo_dev->mem+fifo_dev->current_len,buf,count))

{

ret= -EFAULT;

goto out;

}

else

{

fifo_dev->current_len+=count;

wake_up_interruptible(&fifo_dev->r_wait);

//释放异步读通知道信号

if(fifo_dev->async_queue)

{

kill_fasync(&fifo_dev->async_queue,SIGIO,POLL_IN);

}

ret=count;

}

out:up(&fifo_dev->sem);

out2:remove_wait_queue(&fifo_dev->w_wait,&wait);

set_current_state(TASK_RUNNING);

return ret;

}

static unsigned int fifo_poll(struct file * filp,struct poll_table *wait)

{

int mask=0;

struct FIFO_DEV *fifo_dev=filp->private_data;

down(&fifo_dev->sem);

poll_wait(filp,&fifo_dev->r_wait,wait);

poll_wait(filp,&fifo_dev->w_wait,wait);

if(fifo_dev->current_len!=0)

{

mask|=POLLIN | POLLRDNORM;

}

if(fifo_dev->current_len!=SIZE)

{

mask|=POLLOUT|POLLRDNORM;

}

up(&fifo_dev->sem);

return mask;

}

static const struct file_operations fifo_ops=

{

.owner=THIS_MODULE,

.open=fifo_open,

.release=fifo_release,

.read=fifo_read,

.write=fifo_write,

.poll=fifo_poll,

.fasync=fifo_fasync,

};

int __init fifo_init(void)

{

int ret;

dev_t devno=MKDEV(major,0);

if(major)

{

ret=register_chrdev_region(devno,1,DEVNAME);

}

else

{

ret=alloc_chrdev_region(&devno,0,1,DEVNAME);

major=MAJOR(devno);

}

if(ret<0)

{

return ret;

}

fifo_dev=kmalloc(sizeof(struct FIFO_DEV),GFP_KERNEL);

if(!fifo_dev)

{

ret=-ENOMEM;

goto fail_malloc;

}

memset(fifo_dev,0,sizeof(struct FIFO_DEV));

cdev_init(&fifo_dev->cdev,&fifo_ops);

fifo_dev->cdev.ops=&fifo_ops;

cdev_add(&fifo_dev->cdev,devno,1);

fifo_dev->cdev.owner=THIS_MODULE;

init_MUTEX(&fifo_dev->sem);

init_waitqueue_head(&fifo_dev->r_wait);

init_waitqueue_head(&fifo_dev->w_wait);

fifo_dev->current_len=0;

return 0;

fail_malloc:unregister_chrdev_region(devno,1);

return ret;

}

int __exit fifo_exit(void)

{

cdev_del(&fifo_dev->cdev);

kfree(fifo_dev);

unregister_chrdev_region(MKDEV(major,0),1);

return 0;

}

module_init(fifo_init);

module_exit(fifo_exit);

secondtimer.c:定时器驱动

#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include

#define DEVNAME "SECONDTIMER_DEV"

#define SECONDTIMER_MAJOR 255

int secondtimer_major=SECONDTIMER_MAJOR;

struct SECONDTIMER_DEV

{

struct cdev cdev;

struct timer_list timerlist;

atomic_t totleCount;

};

struct SECONDTIMER_DEV *secondtimer_dev;

static void secondtimer_handler(unsigned args)

{

mod_timer(&secondtimer_dev->timerlist,jiffies+HZ);

atomic_inc(&secondtimer_dev->totleCount);

printk("kernel current fiffies equ %ld\n",jiffies);

}

static int secondtimer_open(struct inode *inode,struct file *filp)

{

filp->private_data=secondtimer_dev;

init_timer(&secondtimer_dev->timerlist);

secondtimer_dev->timerlist.function=&secondtimer_handler;

secondtimer_dev->timerlist.expires=jiffies+HZ;

add_timer(&secondtimer_dev->timerlist);

atomic_set(&secondtimer_dev->totleCount,0);

return 0;

}

static int secondtimer_release(struct inode *inode,struct file *filp)

{

del_timer(&secondtimer_dev->timerlist);

return 0;

}

static ssize_t secondtimer_read(struct file *filp,char __user *buf,size_t count,loff_t *ppos)

{

int counts=0;

struct SECONDTIMER_DEV *secondtimer_dev=filp->private_data;

counts=atomic_read(&secondtimer_dev->totleCount);

if(put_user(counts,(int *)buf))

{

return -EFAULT;

}

else

{

return sizeof(unsigned int);

}

}

static const struct file_operations secondtimer_ops=

{

.owner=THIS_MODULE,

.open=secondtimer_open,

.release=secondtimer_release,

.read=secondtimer_read,

};

int __init secondtimer_init(void)

{

int ret;

dev_t devno=MKDEV(secondtimer_major,0);

if(secondtimer_major)

{

ret=register_chrdev_region(devno,1,DEVNAME);

}

else

{

ret=alloc_chrdev_region(&devno,0,1,DEVNAME);

secondtimer_major=MAJOR(devno);

}

if(ret<0)

{

return ret;

}

secondtimer_dev=kmalloc(sizeof(struct SECONDTIMER_DEV),GFP_KERNEL);

if(!secondtimer_dev)

{

ret=-ENOMEM;

goto fail_malloc;

}

memset(secondtimer_dev,0,sizeof(struct SECONDTIMER_DEV));

cdev_init(&secondtimer_dev->cdev,&secondtimer_ops);

secondtimer_dev->cdev.ops=&secondtimer_ops;

cdev_add(&secondtimer_dev->cdev,devno,1);

secondtimer_dev->cdev.owner=THIS_MODULE;

return 0;

fail_malloc:unregister_chrdev_region(devno,1);

return ret;

}

int __exit secondtimer_exit(void)

{

cdev_del(&secondtimer_dev->cdev);

kfree(secondtimer_dev);

unregister_chrdev_region(MKDEV(secondtimer_major,0),1);

return 0;

}

module_init(secondtimer_init);

module_exit(secondtimer_exit);

makefile内容如下:

obj-m:= fifo.o

obj-m:= secondtimer.o

KERNELDIR:=/lib/modules/$(shell uname -r)/build

default:

make -C $(KERNELDIR) M=$(shell pwd) modules

install:

insmod fifo.ko

mknod /dev/fifo c 248 0

chmod 777 /dev/fifo

insmod secondtimer.ko

mknod /dev/secondtimer c 255 0

chmod 777 /dev/secondtimer

uninstall:

rmmod fifo.ko

rm -f /dev/fifo

rmmod secondtimer.ko

rm -f /dev/secondtimer

clean:

make -C $(KERNELDIR) M=$(shell pwd) clean

2.测试代码

pollTest.c:轮询操作测试

#include #include #include #include #include

#define FIFO_CLEAR 0x1

#define FIFO_LEN 20

main()

{

int fd,num;

char mem_char[FIFO_LEN];

fd_set rfds,wfds;

*mem_char="abc";

fd=open("/dev/fifo",O_RDWR|O_NONBLOCK);

if(fd!=-1)

{

while(1)

{

FD_ZERO(&rfds);

FD_ZERO(&wfds);

FD_SET(fd,&rfds);

FD_SET(fd,&wfds);

select(fd+1,&rfds,&wfds,NULL,NULL);

if(FD_ISSET(fd,&wfds))

{

num=write(fd,"123",FIFO_LEN);

printf("Poll write!\n");

}

if(FD_ISSET(fd,&rfds))

{

num=read(fd,mem_char,FIFO_LEN);

printf("Poll read!\n");

puts(mem_char);

printf("%s\n",mem_char);

}

sleep(2);

}

}

else

{

printf("File open failure!\n");

}

}

//fasynctest.c,异步信号通知测试

#include #include #include #include #include #include #include #include

void input_handler(int signum)

{

printf("receive a signal from fifo,signum %d\n",signum);

sleep(3);

}

main()

{

int fd,oflags;

fd=open("/dev/fifo",O_RDWR,S_IRUSR|S_IWUSR);

if(fd!=-1)

{

signal(SIGIO,input_handler);

fcntl(fd,F_SETOWN,getpid());

oflags=fcntl(fd,F_GETFL);

fcntl(fd,F_SETFL,oflags|FASYNC);

while(1)

{

sleep(2);

}

}

else

{

printf("File open failure!\n");

}

}

secondtimerTest.c:定时器驱动测试

#include #include #include #include #include #include #include #include

main()

{

int fd,counter=0,old_counter=0;

fd=open("/dev/secondtimer",O_RDONLY);

if(fd!=-1)

{

while(1)

{

read(fd,&counter,sizeof(int));

if(counter!=old_counter)

{

printf("current counter is %d\n",counter);

old_counter=counter;

}

sleep(2);

}

}

else

{

printf("File open failure!\n");

}

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值