Chinaunix首页 | 论坛 | 博客
  • 博客访问: 801384
  • 博文数量: 124
  • 博客积分: 1927
  • 博客等级: 上尉
  • 技术积分: 932
  • 用 户 组: 普通用户
  • 注册时间: 2010-08-31 14:06
文章分类

全部博文(124)

文章存档

2018年(5)

2017年(2)

2016年(6)

2015年(4)

2014年(24)

2013年(7)

2012年(11)

2011年(13)

2010年(52)

我的朋友

分类: LINUX

2010-08-31 16:01:17

//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");
    }
}

阅读(1064) | 评论(1) | 转发(0) |
给主人留下些什么吧!~~

chinaunix网友2010-09-02 08:18:39

Download More than 1000 free IT eBooks: http://free-ebooks.appspot.com