网站开发现状,聊天网站怎么建设,wordpress设置伪静态,国内网站linux内核驱动——字符设备实现两个终端单向收发
参考
Ubuntu18.04添加内核模块#xff08;字符设备#xff09;
创建内核驱动文件chat_dev.c#xff1a;
#include linux/init.h //定义了module_init
#include linux/module.h //最基本的头文件字符设备
创建内核驱动文件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.hstatic 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.hint main(int argc, char **argv)
{int fd;char words[1000];fd open(/dev/chat, O_RDWR); //根据设备描述符打开设备if(fd 0) //打开失败printf(cant open\n); while(scanf(%s, words)) //可以自己输入{size_t len strlen(words);words[len] \0;// printf(%s\n, words);write(fd, words, len1); //根据文件描述符调用write}return 0;
}创建接收端测试程序read.c
#include sys/types.h
#include sys/stat.h
#include fcntl.h
#include stdio.h
#include string.hint main(int argc, char **argv)
{int fd;char words[1000];fd open(/dev/chat, O_RDWR); //根据设备描述符打开设备if(fd 0) //打开失败printf(cant 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