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

Linux源码阅读笔记13-进程通信组件中

架构图

代码分析

loff_t lnchannel_llseek(struct file *filp, loff_t offset, int whence) {loff_t newpos;switch(whence) {case 0:newpos = offset;break;case 1:newpos = filp->f_pos + offset;break;case 2:return -EINVAL;}if (newpos < 0 || newpos > LNCHANNEL_SIZE) {return -EINVAL;}filp->f_pos = newpos;return newpos;
}

这段代码是一个文件操作函数lnchannel_llseek(),它用于在文件中进行定位。具体来说,根据参数whenc e的值不同,函数将会根据指定的偏移量进行定位,并返回新的位置。

  • 如果whence为0,则将偏移量直接作为新位置。
  • 如果whence为1,则将当前位置(filp->f_pos)与偏移量相加得到新位置。
  • 如果whence为2,则返回无效参数错误(EINVAL)。

在完成计算新位置之后,函数会对新位置进行合法性检查。如果新位置小于0或大于预定义的文件大小(LNCHANNEL_SIZE),则会返回无效参数错误。

最后,函数更新文件结构体中的当前位置(filp->f_pos)为新位置,并返回新位置值。

unsigned int lnchannel_poll(struct file *filp, struct poll_table_struct *wait) {struct lnchannel* channel = filp->private_data;unsigned int mask = 0;poll_wait(filp, &channel->inq, wait);if (have_data) {mask |= (POLLIN | POLLRDNORM);}return mask;
}

这段代码是一个文件操作函数lnchannel_poll(),用于进行文件的轮询操作。它主要用于检查是否有数据可读,并返回相应的事件掩码。

首先,函数从文件结构体中获取通道指针channel

接下来,使用poll_wait()函数将当前进程加入到等待队列中,以便在有新数据到达时唤醒进程。

然后,在判断是否有数据可读之前,代码中缺少了一个变量have_data的定义和赋值过程。在此处假设该变量为布尔类型,并且已经被正确初始化。

如果存在可读数据,则将事件掩码的对应位(POLLIN | POLLRDNORM)设置为1,表示可读事件发生。

最后,函数返回事件掩码mask给调用者,表示当前的文件状态。

需要注意的是,这只是代码片段,并没有提供完整的上下文环境。如果需要更详细的解释或有其他问题,请随时提问。

完整代码实现

#include <linux/module.h>
#include <linux/types.h>
#include <linux/fs.h>
#include <linux/errno.h>
#include <linux/mm.h>
#include <linux/sched.h>
#include <linux/init.h>
#include <linux/cdev.h>
#include <linux/io.h>
#include <linux/uaccess.h>
#include <linux/slab.h>
#include <linux/poll.h>#ifndef LNCHANNEL_MAJOR
#define LNCHANNEL_MAJOR     96
#endif#ifndef LNCHANNEL_NR_DEVS
#define LNCHANNEL_NR_DEVS   2
#endif#ifndef LNCHANNEL_SIZE
#define LNCHANNEL_SIZE      4096
#endif#define ENABLE_POLL     1struct lnchannel {char* data;unsigned long size;
#if ENABLE_POLLwait_queue_head_t inq;
#endif
};static int channel_major = LNCHANNEL_MAJOR;
module_param(channel_major, int, S_IRUGO);struct lnchannel* channel_devp;
struct cdev cdev;char have_data = 0;loff_t lnchannel_llseek(struct file *filp, loff_t offset, int whence) {loff_t newpos;switch(whence) {case 0:newpos = offset;break;case 1:newpos = filp->f_pos + offset;break;case 2:return -EINVAL;}if (newpos < 0 || newpos > LNCHANNEL_SIZE) {return -EINVAL;}filp->f_pos = newpos;return newpos;
}ssize_t lnchannel_read(struct file *filp, char __user *buffer, size_t size, loff_t *ppos) {int ret = 0;unsigned long count = size;unsigned long long p = *ppos;struct lnchannel* channel = filp->private_data;if (p >= LNCHANNEL_SIZE) {return 0;}if (count > LNCHANNEL_SIZE - p) {count = LNCHANNEL_SIZE - p;}while(!have_data) {if (filp->f_flags & O_NONBLOCK) {return -EAGAIN;}wait_event_interruptible(channel->inq, have_data);}if (copy_to_user(buffer, (void*)(channel->data + p), count)) {ret = -EFAULT;}else {ret = strlen(buffer);channel->size -= ret;printk(KERN_INFO "read %d btye(s) from %ld\n", ret, p);}have_data = 0;return ret;
}ssize_t lnchannel_write(struct file *filp, const char __user *buffer, size_t size, loff_t * ppos) {int ret = 0;unsigned long count = size;unsigned long long p = *ppos;struct lnchannel* channel = filp->private_data;if (p >= LNCHANNEL_SIZE) {return ret;}if (count >= LNCHANNEL_SIZE - p) {count = LNCHANNEL_SIZE - p;}if (copy_from_user(channel->data + p, buffer, count)) {return -EFAULT;}else {*(channel->data + p + count) = '\0';channel->size += count;ret = count;*ppos += count;printk(KERN_INFO, "written %d btyes from %ld\n", count, p);}have_data = 1;wake_up(channel->inq);return ret;
}int lnchannel_mmap(struct file *filp, struct vm_area_struct *vma) {vma->vm_flags |= VM_IO;vma->vm_flags |= (VM_DONTEXPAND | VM_DONTDUMP);if (remap_pfn_range(vma, vma->vm_start, virt_to_phys(channel->data) >> PAGE_SHIFT, vma->vm_end-vma->vm_start, vma->vm_page_prot)) {return -EAGAIN;}return 0;
}int lnchannel_open(struct inode *inode, struct file *filp) {struct lnchannel* channel;int num = MINOR(inode->i_cdev);if (num >= LNCHANNEL_NR_DEVS) {return -ENODEV;}channel = &channel_devp[num];filp->private_data = channel;return 0;}int lnchannel_release(struct inode *, struct file *) {return 0;
}unsigned int lnchannel_poll(struct file *filp, struct poll_table_struct *wait) {struct lnchannel* channel = filp->private_data;unsigned int mask = 0;poll_wait(filp, &channel->inq, wait);if (have_data) {mask |= (POLLIN | POLLRDNORM);}return mask;
}static const struct file_operations lnchannel_fops = {.owner = THIS_MODULE,.llseek = lnchannel_llseek,.open = lnchannel_open,.write = lnchannel_write,.open = lnchannel_open,.release = lnchannel_release,.mmap = lnchannel_mmap,.poll = lnchannel_poll,
};static int lnchannel_init(void) {int result;int i;dev_t devno = MKDEV(channel_major, 0);if (channel_major) {result = register_chrdev_region(devno, LNCHANNEL_NR_DEVS, "lnchannel");}else {result = alloc_chrdev_region(&devno, 0, LNCHANNEL_NR_DEVS, "lnchannel");channel_major = MAJOR(devno);}if (result < 0) return result;cdev_init(&cdev, &lnchannel_fops);cdev.owner = THIS_MODULE;cdev_add(&cdev, MKDEV(channel_major, 0), LNCHANNEL_NR_DEVS);channel_devp = kmalloc(LNCHANNEL_NR_DEVS * (struct lnchannel), GFP_KERNEL);if (!channel_devp) {result = -ENOMEM;goto fail_malloc;}memset(channel_devp, 0, sizeof(struct lnchannel));for(i = 0; i < LNCHANNEL_NR_DEVS; i++) {channel_devp[i].size = LNCHANNEL_SIZE;channel_devp[i].data = kmalloc(LNCHANNEL_SIZE, GFP_KERNEL);memset(channel_devp[i].data, 0, LNCHANNEL_SIZE);init_waitqueue_head(&(channel_devp[i].inq));}printk(KERN_INFO "linchannel_init");return 0;fail_malloc:unregister_chrdev_region(devno, 1);return result;
}static void lnchannel_exit(void) {printk(KERN_INFO "lnchannel_exit");cdev_del(&cdev);kfree(channel_devp);unregister_chrdev_region(MKDEV(channel_major, 0), 2);
}MODULE_AUTHOR("Lenn Louis");
MODULE_LICENSE("GPL");module_init(lnchannel_init);
module_init(lnchannel_exit);
#!/bin/bashccflags_y += -O2ifneq ($(KERNELRELEASE),)
obj-m := lnchannel.o
else
KERNELDIR ?= /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)default:$(MAKE) -C $(KERNELDIR) M=$(PWD) modules 
endifclean:rm -rf *.o *.ko *.mod.cdepend .depend dep:$(CC)  -M *.c > .depend 

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 大厂linux面试题攻略五之数据库管理
  • delphi 12 学习如何登陆网站下载文件
  • 消息队列:Kafka吞吐量为什么比RocketMQ大
  • 3.特征工程-特征抽取、特征预处理、特征降维
  • 第一阶段面试问题(后半部分)
  • java之IO篇——File、字节流、字符流
  • 【IO】使用有名管道实现,一个进程用于给另一个进程发消息,另一个进程收到消息后,展示到终端上,并且将消息保存到文件上一份
  • 新书速览|AI创意商业广告设计:Adobe Firefly + Photoshop
  • 现代前端架构介绍(第一部分):App是如何由不同的构建块构成的
  • 数据中台建设之数据汇聚与数据交换
  • Apache Pig: 高级数据处理平台
  • 【开源】嵌入式Linux(IMX6U)应用层综合项目(1)--云平台调试APP
  • 网络流算法:最大流问题
  • SparkSQL---编程模型的操作,数据加载与落地及自定义函数的使用
  • 最新全国各省市水系矢量数据(2024年更新)
  • [笔记] php常见简单功能及函数
  • 【140天】尚学堂高淇Java300集视频精华笔记(86-87)
  • 【每日笔记】【Go学习笔记】2019-01-10 codis proxy处理流程
  • git 常用命令
  • JS学习笔记——闭包
  • MyEclipse 8.0 GA 搭建 Struts2 + Spring2 + Hibernate3 (测试)
  • Redis学习笔记 - pipline(流水线、管道)
  • spring security oauth2 password授权模式
  • 闭包--闭包作用之保存(一)
  • 当SetTimeout遇到了字符串
  • 离散点最小(凸)包围边界查找
  • 前端临床手札——文件上传
  • 使用docker-compose进行多节点部署
  • 思维导图—你不知道的JavaScript中卷
  • 小程序、APP Store 需要的 SSL 证书是个什么东西?
  • 小程序01:wepy框架整合iview webapp UI
  • 一文看透浏览器架构
  • k8s使用glusterfs实现动态持久化存储
  • ​Distil-Whisper:比Whisper快6倍,体积小50%的语音识别模型
  • ​iOS安全加固方法及实现
  • ​如何使用ArcGIS Pro制作渐变河流效果
  • # 达梦数据库知识点
  • # 执行时间 统计mysql_一文说尽 MySQL 优化原理
  • (1)常见O(n^2)排序算法解析
  • (4) PIVOT 和 UPIVOT 的使用
  • (C11) 泛型表达式
  • (c语言)strcpy函数用法
  • (顶刊)一个基于分类代理模型的超多目标优化算法
  • (附源码)springboot家庭财务分析系统 毕业设计641323
  • (三)centos7案例实战—vmware虚拟机硬盘挂载与卸载
  • (算法)N皇后问题
  • (算法)大数的进制转换
  • (一)appium-desktop定位元素原理
  • (转)chrome浏览器收藏夹(书签)的导出与导入
  • (自用)gtest单元测试
  • **PyTorch月学习计划 - 第一周;第6-7天: 自动梯度(Autograd)**
  • .bat批处理(十):从路径字符串中截取盘符、文件名、后缀名等信息
  • .net dataexcel 脚本公式 函数源码
  • .Net Remoting(分离服务程序实现) - Part.3
  • .NET 直连SAP HANA数据库