#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/device.h>
#include <linux/slab.h>
#include <linux/uaccess.h>
#include <linux/sched.h>
#define CDEVNAME "mycdev"
const int count = 3;
int major = 0;
int minor = 0;
struct class *cls;
struct device *dev;
struct cdev *cdev;
char kbuf[128] = {0};
int condition=0;
wait_queue_head_t wq;
int mycdev_open(struct inode *inode, struct file *file)
{
printk("%s:%s:%d\n",__FILE__,__func__,__LINE__);
return 0;
}
ssize_t mycdev_read(struct file *file, char __user *ubuf,
size_t size, loff_t *offs)
{
int ret;
printk("%s:%s:%d\n",__FILE__,__func__,__LINE__);
//1.¿¿¿¿¿¿
if(file->f_flags&O_NONBLOCK)
{
//¿¿¿
return -EINVAL;
}
else
{
ret=wait_event_interruptible(wq,condition);
if(ret)
{
printk("wait err\n");
return ret;
}
}
//3.¿¿¿¿,¿¿¿¿¿¿¿
if(size > sizeof(kbuf)) size = sizeof(kbuf);
ret = copy_to_user(ubuf,kbuf,size);
if(ret){
printk("copy data to user error\n");
return -EINVAL;
}
//4.¿¿¿condition¿¿¿¿¿
condition=0;
return size;
}
ssize_t mycdev_write(struct file *file, const char __user *ubuf,
size_t size, loff_t *offs)
{
int ret;
printk("%s:%s:%d\n",__FILE__,__func__,__LINE__);
if(size > sizeof(kbuf)) size = sizeof(kbuf);
ret = copy_from_user(kbuf,ubuf,size);
if(ret){
printk("copy data from user error\n");
return -EINVAL;
}
condition=1;
wake_up_interruptible(&wq);
return size;
}
int mycdev_close(struct inode *inode, struct file *file)
{
printk("%s:%s:%d\n",__FILE__,__func__,__LINE__);
return 0;
}
const struct file_operations fops = {
.open = mycdev_open,
.read = mycdev_read,
.write = mycdev_write,
.release = mycdev_close,
};
static int __init mycdev_init(void)
int ret,i;
dev_t devm;
//1.·ÖÅä¶ÔÏó
cdev = cdev_alloc();
if(cdev == NULL){
printk("alloc memory error\n");
ret = -ENOMEM;
goto ERR_STEP0;
}
//2.³õʼ»¯
cdev_init(cdev,&fops);
//3.É豸ºÅµÄÉêÇë
if(major > 0){
//ÊÖ¶¯Ö¸¶¨
ret = register_chrdev_region(MKDEV(major,minor),
count,CDEVNAME);
if(ret){
printk("static:alloc device number error\n");
goto ERR_STEP1;
}
}else{
//×Ô¶¯ÉêÇë
ret = alloc_chrdev_region(&devm,minor,count,CDEVNAME);
if(ret){
printk("dynaimc:alloc device number error\n");
goto ERR_STEP1;
}
major = MAJOR(devm);
minor = MINOR(devm);
}
//4.×¢²á
ret = cdev_add(cdev,MKDEV(major,minor),count);
if(ret){
printk("char device register error\n");
goto ERR_STEP2;
}
//5.´´½¨class
cls = class_create(THIS_MODULE,CDEVNAME);
if(IS_ERR(cls)){
printk("class create error\n");
ret = PTR_ERR(cls);
goto ERR_STEP3;
}
//6.´´½¨device
for(i=0; i<count; i++){
dev = device_create(cls,NULL,MKDEV(major,i),NULL,"mycdev%d",i);
if(IS_ERR(dev)){
printk("device%d create error\n",i);
ret = PTR_ERR(dev);
goto ERR_STEP4;
}
}
init_waitqueue_head(&wq);
return 0; //²»ÄܺöÂÔ
ERR_STEP4:
for(--i; i>=0; i--){
device_destroy(cls,MKDEV(major,i));
}
class_destroy(cls);
ERR_STEP3:
cdev_del(cdev);
ERR_STEP2:
unregister_chrdev_region(MKDEV(major,minor),count);
ERR_STEP1:
kfree(cdev);
ERR_STEP0:
return ret;
}
static void __exit mycdev_exit(void)
{
int i;
for(i=0; i<count; i++){
device_destroy(cls,MKDEV(major,i));
}
class_destroy(cls);
cdev_del(cdev);
unregister_chrdev_region(MKDEV(major,minor),count);
kfree(cdev);
}
module_init(mycdev_init);
module_exit(mycdev_exit);
MODULE_LICENSE("GPL");
———————————————————————————————————————————
#include <stdio.h>
2 #include <sys/types.h>
3 #include <sys/stat.h>
4 #include <fcntl.h>
5 #include <unistd.h>
6 #include <string.h>
7
8 char buf[128] = {0};
9
10 int main(int argc, const char *argv[])
11 {
12 int fd;
13 pid_t pid;
14 fd=open("/dev/mycdev0",O_RDWR);
15 pid=fork();
16 if(pid<0)
17 {
18 perror("fork fail\n");
19 return -1;
20 }
21 else if(pid==0)
22 {
23 while(1)
24 {
25 memset(buf,0,sizeof(buf));
26 read(fd,buf,sizeof(buf));
27 printf("read data = %s\n",buf);
28 }
29 }
30 else
31 {
32 while(1)
33 {
34 sleep(5);
35 // write(fd,buf,sizeof(buf));
36 }
37 }
close(fd);
40
41 return 0;
42 }