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.wrglobalvar.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),)obj−m:=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