当前位置: 首页 > news >正文

linux内核驱动——字符设备实现两个终端单向收发

linux内核驱动——字符设备实现两个终端单向收发

参考

Ubuntu18.04添加内核模块(字符设备)

  • 创建内核驱动文件chat_dev.c
#include <linux/init.h>     //定义了module_init
#include <linux/module.h>   //最基本的头文件,其中定义了MODULE_LICENSE这一类宏
#include <linux/fs.h>       // file_operations结构体定义在该头文件中
#include <linux/device.h>    //class、device结构体的定义位置
#include <linux/sched/signal.h>
#include <linux/uaccess.h>    // copy_to_user & copy_from_user 
#include <linux/mutex.h>static const char* device_name = "chat_driver";  //  定义设备名
static const char* device_path = "chat";  //  定义设备文件名  /dev/chat
static struct class *chat_class;    //定义class结构体
static struct device *chat_dev;    //定义device结构体//定义了open函数
static int chat_drv_open (struct inode *inode, struct file *file)
{printk("open\n");return 0;
}static char words[1000];  //聊天内容缓存
static int words_cnt = 0;  //聊天内容缓存字节数
static struct mutex words_mutex; //互斥锁
//read函数
static ssize_t chat_drv_read(struct file *file, char __user *buf, size_t size, loff_t *fpos) {printk("read begin\n");ssize_t cnt = 0;  //返回值,表示读取字节长度mutex_lock(&words_mutex);  //上锁if(words_cnt > 0){copy_to_user(buf, words, words_cnt); //数据拷贝到用户态printk("words_cnt=%d\n", words_cnt);cnt = words_cnt;words_cnt = 0;  //读取后缓存清空}mutex_unlock(&words_mutex); //解锁printk("read finish\n");return cnt;
}//定义了write函数
static ssize_t chat_drv_write (struct file *file, const char __user *buf, size_t size, loff_t * ppos)
{printk("write begin\n");mutex_lock(&words_mutex); //上锁copy_from_user(words, buf, size);  //从用户态拷贝数据words_cnt = size;       //更新缓存字节长度printk("words_cnt=%d\n", words_cnt);printk("words=%s\n", words);mutex_unlock(&words_mutex); //解锁printk("write finish\n");return 0;
}//在file_operations中注册open和write函数
static struct file_operations chat_drv_fo =
{.owner  =  THIS_MODULE,//将对应的函数关联在file_operations的结构体中.open   =  chat_drv_open,    .read    = chat_drv_read,  .write  =  chat_drv_write,
};static int dev_id = 0;     //初始化的设备号0
//init驱动的入口函数
static int __init chat_drv_init(void)
{      //注册设备,实际是将file_operations结构体放到内核的制定数组中,以便管理//在register_chrdev中制定dev_id作为主设备号,若dev_id为0则自动分配一个主设备号dev_id = register_chrdev(dev_id, device_name , &chat_drv_fo);chat_class = class_create(THIS_MODULE, device_path);    //初始化class结构体,指定设备文件名chat_dev = device_create(chat_class, NULL, MKDEV(dev_id, 0), NULL, device_path);// 根据class来初始化device,会创建出对应的设备文件mutex_init(&words_mutex);printk("init\n");return 0;
}//驱动的出口函数
static void __exit chat_drv_exit(void)
{printk("exit\n");unregister_chrdev(dev_id, device_name);  //卸载设备,实际是将file_operations结构体从内核维护的相关数组中以主设备号作为索引删除device_unregister(chat_dev); // 后创建的先卸载class_destroy(chat_class);
}//内核将通过这个宏,来直到这个驱动的入口和出口函数
module_init(chat_drv_init);  
module_exit(chat_drv_exit);MODULE_LICENSE("GPL");  //指定协议
  • 编译并加载内核驱动,详细可以看参考

  • 创建发送端测试程序write.c

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>int main(int argc, char **argv)
{int fd;char words[1000];fd = open("/dev/chat",  O_RDWR);  //根据设备描述符打开设备if(fd < 0)          //打开失败printf("can't open\n");  while(scanf("%s", words))  //可以自己输入{size_t len = strlen(words);words[len] = '\0';// printf("%s\n", words);write(fd, words, len+1);  //根据文件描述符调用write}return 0;
}
  • 创建接收端测试程序read.c
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>int main(int argc, char **argv)
{int fd;char words[1000];fd = open("/dev/chat",  O_RDWR);  //根据设备描述符打开设备if(fd < 0)          //打开失败printf("can't open\n");  while(1){int ret = read(fd, words, 5);  //根据文件描述符调用write,这里的5实际上没有用处if(ret > 0)printf("%s\n", words); sleep(1); }return 0;
}
  • 编译两个测试程序,并分别在两个终端运行:
gcc write.c -o write
gcc read.c -o read
  • 结果如下:
$ sudo ./write
nihao
qpwoeiruty
12222222222222rrrrrrrrrrrrrrrrrrrrrrrrrrrr
$ sudo ./read
nihao
qpwoeiruty
12222222222222rrrrrrrrrrrrrrrrrrrrrrrrrrrr
http://www.lryc.cn/news/312811.html

相关文章:

  • 读取CSV数据并写入MySQL
  • centos7.4下升级最新的ssh
  • Java实现的双向链表示例
  • 生物电信号测量技术
  • 【开源】JAVA+Vue.js实现创意工坊双创管理系统
  • Python基于opencv的人脸识别上课签到考勤系统,附源码
  • 【HTML】HTML基础7.2(有序列表)
  • ucode usage使用方法
  • HCIA-HarmonyOS设备开发认证V2.0-习题
  • 【深度学习笔记】优化算法——随机梯度下降
  • oss-fuzz-gen:一款基于LLM的模糊测试对象生成与评估框架
  • 深度神经网络 基本知识 记录
  • 基于Springboot免费搭载轻量级阿里云OSS数据存储库(将本地文本、照片、视频、音频等上传云服务保存)
  • RK3568 Android12 适配抖音 各大APP
  • [渗透教程]-022-内网穿透的高性能的反向代理应用
  • 【计算机网络】深度学习HTTPS协议
  • C盘新建的文件夹内需要管理员权限才能新建和删除解决问题记录
  • 2024年【道路运输企业安全生产管理人员】考试报名及道路运输企业安全生产管理人员免费试题
  • 四面体单元悬臂梁的Matlab有限元编程 | 实体单元 | Matlab源码 | 理论文本
  • BurpSuite2024.2.1
  • 【投稿优惠|火热征稿】2024年计算机技术与自动化发展国际会议 (ICCTAD 2024)
  • LeetCode.232. 用栈实现队列
  • SpringBoot集成ElasticSearch(ES)
  • 基于STC12C5A60S2系列1T 8051单片机的TM1638键盘数码管模块的数码管显示应用
  • Qt插件之输入法插件的构建和使用(一)
  • 慢SQL调优-索引详解
  • 知乎语音下载(mediadown)
  • 2023 最新 IntelliJ IDEA 2023.3 详细配置步骤演示:新入职如何快速配置 IntelliJ IDEA?
  • Linux 下安装 Git
  • Manomotion 实现AR手势互动-解决手势无效的问题