linux驱动程序设计

这个博客展示了Linux内核中字符设备驱动的实现,包括`read.c`、`write.c`和`globalvar.c`三个部分。`globalvar.c`定义了一个全局变量设备,实现了读写操作,使用信号量和等待队列处理并发访问。`read.c`和`write.c`分别是用户空间的读写程序,通过打开设备文件进行交互。整个示例详细地解释了如何在Linux中注册、打开、读取和关闭字符设备。
摘要由CSDN通过智能技术生成

read.c
#include<sys/types.h>
#include<unistd.h>
#include<sys/stat.h>
#include<stdio.h>
#include<fcntl.h>
#include<string.h>
int main(){
int fd,i;
char msg[100];
fd=open("/dev/globalvar",O_RDWR,S_IRUSR|S_IWUSR);
if(fd!=-1)
{
while(1)
{
for(i=0;i<100;i++)
msg[i]=’\0’;
read(fd,msg,strlen(msg));
printf("%s\n",msg);
if(strcmp(msg,“quit”)==0)
{
close(fd);
break;
}
}
}
else
{
printf(“device open failure,%d\n”,fd);
}
return 0;
}
write.c
#include<sys/types.h>
#include<unistd.h>
#include<sys/stat.h>
#include<stdio.h>
#include<fcntl.h>
#include<string.h>
int main()
{
int fd;
char msg[100];
fd= open("/dev/chardev0",O_RDWR,S_IRUSR|S_IWUSR);
if(fd!=-1)
{
while(1)
{
printf(“Please input the globar:\n”);
scanf("%s",msg);
write(fd,msg,strlen(msg));
if(strcmp(msg,“quit”)==0)
{
close(fd);
break;
}
}
}
else
{
printf(“device open failure\n”);
}
return 0;
}

globalvar.c
#include<linux/module.h>
#include<linux/init.h>
#include<linux/fs.h>
#include<asm/uaccess.h>
#include<linux/wait.h>
#include<linux/semaphore.h>
#include<linux/sched.h>
#include<linux/cdev.h>
#include<linux/types.h>
#include<linux/kdev_t.h>
#include<linux/device.h>
#define MAXNUM 100
#define MAJOR_NUM 201/主设备号/
struct dev{
struct cdev devm;/字符设备/
struct semaphore sem;
wait_queue_head_t outq;/等待队列实现阻塞操作/
int flag;/阻塞唤醒标志/
char buffer[MAXNUM+1];
char *rd,*wr,*end;/读写指针/
}globalvar;
static struct class *my_class;
int major=MAJOR_NUM;
static ssize_t globalvar_read(struct file *,char *,size_t,loff_t *);
static ssize_t globalvar_write(struct file *,const char *,size_t,loff_t *);
static int globalvar_open(struct inode *inode,struct file *filp);
static int globalvar_release(struct inode *inode,struct file *filp);
/初始化字符设备驱动的file_operations结构体/
struct file_operations globalvar_fops=
{
.read=globalvar_read,
.write=globalvar_write,
.open=globalvar_open,
.release=globalvar_release,
};
static int globalvar_init(void){
int result=0;
int err=0;
dev_t dev=MKDEV(major,0);
if(major)
{
/静态申请设备号/
result=register_chrdev_region(dev,1,“globalvar”);
}
else
{
/动态分配设备号/
result=alloc_chrdev_region(&dev,0,1,“globalvar”);
major=MAJOR(dev);
}
if(result<0)
return result;
cdev_init(&globalvar.devm,&globalvar_fops);
globalvar.devm.owner=THIS_MODULE;
err=cdev_add(&globalvar.devm,dev,1);
if(err)
printk(KERN_INFO"Error %d adding char_mem device",err);
else
{
printk(“globalvar register success\n”);
sema_init(&globalvar.sem,1);/初始化信号量/
init_waitqueue_head(&globalvar.outq);/初始化等待队列/
globalvar.rd=globalvar.buffer;/读指针/
globalvar.wr=globalvar.buffer;/写指针/
globalvar.end=globalvar.buffer+MAXNUM;/缓冲区尾指针/
globalvar.flag=0;/阻塞唤醒标志置为0/
}
my_class=class_create(THIS_MODULE,“chardev0”);
device_create(my_class,NULL,dev,NULL,“chardev0”);
return 0;
}
static int globalvar_open( struct inode *inode,struct file *filp)
{
try_module_get(THIS_MODULE);/模块记数加1/
printk(“THis chrdev is in open\n”);
return(0);
}
static int globalvar_release(struct inode *inode,struct file *filp)
{
module_put(THIS_MODULE);/模块数减1/
printk(“THis chrdev is in release\n”);
return (0);
}
static void globalvar_exit(void)
{
device_destroy(my_class,MKDEV(major,0));
class_destroy(my_class);
cdev_del(&globalvar.devm);
unregister_chrdev_region(MKDEV(major,0),1);
}
static ssize_t globalvar_read(struct file *filp,char *buf,size_t len,loff_t *off)
{
if(wait_event_interruptible(globalvar.outq,globalvar.flag!=0))/不可读时阻塞进程/
{
return -ERESTARTSYS;
}
if(down_interruptible(&globalvar.sem))/P操作/
{
return -ERESTARTSYS;
}
globalvar.flag=0;
printk(“into the read function\n”);
if(globalvar.rd < globalvar.wr)
len=min(len,(size_t)(globalvar.wr-globalvar.rd));
else
len=min(len,(size_t)(globalvar.end-globalvar.rd));
printk(“the len is %ld\n”,len);
/将globalvar从内核空间复制到用户空间buf/
if(copy_to_user(buf,&globalvar.rd,len))
{
printk(KERN_ALERT"copy failed\n");
up(&globalvar.sem);
return -EFAULT;
}
printk(“the read bufffer is %s\n”,globalvar.buffer);
globalvar.rd=globalvar.rd+len;
if(globalvar.rdglobalvar.end)
globalvar.rd=globalvar.buffer;/字符缓冲区循环/
up(&globalvar.sem);/V操作/
return len;
}
static ssize_t globalvar_write(struct file *filp,const char *buf,size_t len,loff_t *off)
{
if(down_interruptible(&globalvar.sem))/P操作/
{
return -ERESTARTSYS;
}
if(globalvar.rd <= globalvar.wr)
len=min(len,(size_t)(globalvar.end-globalvar.wr));
else
len=min(len,(size_t)(globalvar.rd-globalvar.wr-1));
printk(“the write len is %ld\n”,len);
/将用户空间的数据复制到内核空间的global_var/
if(copy_from_user(globalvar.wr,buf,len))
{
up(&globalvar.sem);/V操作/
return -EFAULT;
}
printk(“the write buffer is %s\n”,globalvar.buffer);
printk(“the len of buffer is %ld\n”,strlen(globalvar.buffer));
globalvar.wr=globalvar.wr+len;
if(globalvar.wr
globalvar.end)
globalvar.wr=globalvar.buffer;/循环/
up(&globalvar.sem);/V操作/
globalvar.flag=1;/条件成立可以唤醒进程/
wake_up_interruptible(&globalvar.outq);/唤醒进程/
return len;
}
module_init(globalvar_init);
module_exit(globalvar_exit);
MODULE_LICENSE(“GPL”);

Makefile
ifneq ( ( K E R N E L R E L E A S E ) , ) o b j − m : = g l o b a l v a r . o e l s e K E R N E L D I R : = / l i b / m o d u l e s / (KERNELRELEASE),) obj-m :=globalvar.o else KERNELDIR :=/lib/modules/ (KERNELRELEASE),)objm:=globalvar.oelseKERNELDIR:=/lib/modules/(shell uname -r)/build
PWD :=$(shell pwd)
modules:
$(MAKE) -C ( K E R N E L D I R ) M = (KERNELDIR) M= (KERNELDIR)M=(PWD) modules
endif
clean:
$(MAKE) -C ( K E R N E L D I R ) M = (KERNELDIR) M= (KERNELDIR)M=(PWD) clean

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值