我为虚拟字符设备制作了驱动程序,并尝试从设备(文件)中写入和读取数据。我能够写入数据但是在选择读取时,没有任何内容被读取和打印,程序返回:
myapp.c
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#define DEVICE "/dev/chardriver"
int main()
{
int i,fd;
char ch,write_buf[100],read_buf[100];
fd=open(DEVICE,O_RDWR);
if(fd==-1)
{
printf("file %s either does not exist or has been locked by another process\n",DEVICE);
exit(-1);
}
printf("r=read from device\nw=write to device\nenter command:");
scanf("%c",&ch);
switch(ch)
{
case 'w':
printf("enter data:");
scanf("%s",write_buf);
write(fd,write_buf,sizeof(write_buf));
break;
case 'r':
read(fd,read_buf,sizeof(read_buf));
printf("device: %s\n",read_buf);
break;
default:
printf("command not recognized\n");
break;
}
close(fd);
return 0;
}
终端输出:
anubhav@anubhav-Inspiron-3421:~/Desktop/os$ ./myapp
r=read from device
w=write to device
enter command:w
enter data:hello world
anubhav@anubhav-Inspiron-3421:~/Desktop/os$ ./myapp
r=read from device
w=write to device
enter command:r
device:
anubhav@anubhav-Inspiron-3421:~/Desktop/os$
以下是设备上的权限:
anubhav@anubhav-Inspiron-3421:~/Desktop/os$ ls -l /dev/chardriver
crwxrwxrwx 1 root root 250, 0 Mar 14 10:09 /dev/chardriver
这是我的模块代码:
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/fs.h> //provides file operations structures
#include <linux/cdev.h> //helps register char driver
#include <linux/semaphore.h> //to access semaphores
#include <asm/uaccess.h> //copytouser,copyfromuser
//create my device
struct my_device
{
char data[100];
struct semaphore sem;
} vdevice;
struct cdev *mcdev; //this is device driver
int majornumber; //majorno from dev_num
int ret;
dev_t dev_num;
#define DEVICE_NAME "mydevice"
int device_open(struct inode *inode,struct file *filp)
{
if(down_interruptible(&vdevice.sem)!=0)
{
printk(KERN_ALERT "can't lock device during open");
return -1;
}
printk(KERN_INFO "opened my device");
return 0;
}//end device_open
ssize_t device_read(struct file *filp,char* bufstoredata,size_t bufcount,loff_t* curoffset)
{
printk(KERN_INFO "Reading from device");
ret=copy_to_user(bufstoredata,vdevice.data,bufcount);
return ret;
}
ssize_t device_write(struct file *filp,const char* bufsourcedata,size_t bufcount,loff_t* curoffset)
{
printk(KERN_INFO "Writing to device");
ret=copy_to_user(vdevice.data,bufsourcedata,bufcount);
return ret;
}
int device_close(struct inode *inode,struct file *filp)
{
up(&vdevice.sem);
printk(KERN_INFO "device closed");
return 0;
}
//file operations structure
struct file_operations fops={
.owner=THIS_MODULE,
.open=device_open,
.release=device_close,
.write=device_write,
.read=device_read
};
static int driver_entry(void)
{
//registers the functionalities of driver to system
ret=alloc_chrdev_region(&dev_num,0,1,DEVICE_NAME);
if(ret<0)
{
printk(KERN_ALERT "failed to give major no.");
return ret;
}
majornumber=MAJOR(dev_num);
printk(KERN_INFO "your major no. is %d",majornumber);
printk(KERN_INFO "\tuse \"mknod /dev/%s c %d 0\" for device file",DEVICE_NAME,majornumber);
//create cdev structure
mcdev=cdev_alloc();
mcdev->ops=&fops;
mcdev->owner=THIS_MODULE;
//now we add cdev to kernel
ret=cdev_add(mcdev,dev_num,1);
if(ret<0)
{
printk(KERN_ALERT "failed to add cdev to kernel");
return ret;
}
sema_init(&vdevice.sem,1);
return 0;
}
static void driver_exit(void)
{
cdev_del(mcdev);
unregister_chrdev_region(dev_num,1);
printk(KERN_ALERT "unloaded module");
}
module_init(driver_entry);
module_exit(driver_exit);