在应用层编写程序,终端输入1,内核打印开灯,终端输入0,内核打印关灯
应用层代码:
test.c
#include<stdlib.h>
#include<stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include<unistd.h>
#include<string.h>
int main(int argc, char *argv[])
{
int fd;
char buf[100]={0};
//打开设备文件
fd = open("/dev/mychrdev",O_RDWR);
if(fd < 0)
{
printf("open failed!\n");
exit(-1);
}
while(1)
{
printf("please input>>>>>");
//从终端读取数据
fgets(buf,sizeof(buf),stdin);
buf[strlen(buf)-1] = '\0';
if (!strcmp(buf,"quit"))
{
break;
}
//将数据写入设备文件
write(fd,buf,sizeof(buf));
//清空buf
memset(buf,0,sizeof(buf));
//从设备文件读取数据
read(fd,buf,sizeof(buf));
printf("buf returned from kernel:%s\n",buf);
}
//关闭设备文件
close(fd);
return 0;
}
驱动代码:
mychrdev.c
#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include<linux/uaccess.h>
int major;
char kbuf[128]={0};
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 *ubuf, size_t size, loff_t *lof)
{
int ret;
printk("%s:%s:%d\n",__FILE__,__func__,__LINE__);
//校验传输数据的大小,如果用户空间写的数据比内核空间数据大小大,就给内核支持的最大大小,需要更正大小
if(size > sizeof(kbuf))
size = sizeof(kbuf);
//将数据从内核空间拷贝到用户空间
ret = copy_to_user(ubuf,kbuf,size);
if(ret < 0)
{
printk("copy_to_user failed!\n");
return -1;
}
return 0;
}
ssize_t mycdev_write(struct file *file, const char *ubuf, size_t size, loff_t *lof)
{
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 < 0)
{
printk("copy_from_user failed!\n");
return -1;
}
//如果kbuf中的值为1 --->开灯
if('1'==kbuf[0])
strcpy(kbuf,"led on!\n");
//如果kbuf中的值为0 --->关灯
else if('0'==kbuf[0])
strcpy(kbuf,"led off!\n");
return 0;
}
int mycdev_close(struct inode *inode, struct file *file)
{
printk("%s:%s:%d\n",__FILE__,__func__,__LINE__);
return 0;
}
//定义操作方法结构体变量并赋值
struct file_operations fops = {
.open = mycdev_open,
.read = mycdev_read,
.write = mycdev_write,
.release = mycdev_close,
};
static int __init mycdev_init(void)
{
//字符设备驱动注册
major = register_chrdev(0,"mycdev",&fops);
//判断返回值
if(major < 0)
{
printk("register_chrdev failed!\n");
return -1;
}
//打印主设备号
printk("major = %d\n",major);
return 0;
}
static void __exit mycdev_exit(void)
{
//注销字符设备驱动
unregister_chrdev(major,"mycdev");
}
module_init(mycdev_init);
module_exit(mycdev_exit);
MODULE_LICENSE("GPL");
测试结果