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

news2024/11/13 15:12:44

架构图

代码分析

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     1

struct lnchannel {
    char* data;
    unsigned long size;
#if ENABLE_POLL
    wait_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/bash

ccflags_y += -O2

ifneq ($(KERNELRELEASE),)
obj-m := lnchannel.o
else
KERNELDIR ?= /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)

default:
	$(MAKE) -C $(KERNELDIR) M=$(PWD) modules 
endif

clean:
	rm -rf *.o *.ko *.mod.c

depend .depend dep:
	$(CC)  -M *.c > .depend 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1983422.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

剪映国际版(CapCut) 2024 下载 安装 汉化

将 剪映国际版&#xff08;CapCut&#xff09; 2024 压缩包解压到本地&#xff1a; 点击蓝色字体下载压缩包 提取码 jwsg 鼠标右键 点击 CapCut 3.0.0.exe 选择 以管理员身份运行&#xff1a; 勾选 Agree with CapCut Users License Agreement & Pricacy Policy 点击 Mor…

基于SSM的哈米音乐实战项目,Java课程设计作业,Java毕业设计项目,找工作前的实战项目,附部分源码以及数据库

1、项目所需技术 java基础&#xff0c;java反射&#xff0c;泛型html&#xff0c;css&#xff0c;JavaScript&#xff0c;jquery&#xff0c;bootstrap&#xff0c;layuijstl&#xff0c;el表达式&#xff0c;jsp&#xff0c;mysql&#xff0c;jdbc&#xff0c;xml&#xff0c…

HashMap及其相关知识点

一、HashMap插入与删除 通过将key转换为hashCode&#xff08;int&#xff09;&#xff0c;通过hashCode计算下标&#xff0c;int index hashCode & (length - 1)&#xff0c;从而实现插入与删除。 二、Hash冲突 Java8之前&#xff1a;通过数组链表的数据结构解决hash冲…

【Java数据结构】Map和Set超详细两万字讲解(内含搜索树+哈希表)

&#x1f512;文章目录&#xff1a; 1.❤️❤️前言~&#x1f973;&#x1f389;&#x1f389;&#x1f389; 2. Map和Set的基础概念 3.Map的基础使用 4.Set的基础使用 5. TreeMap的本质——红黑树 5.1二叉搜索树的概念 5.2二叉搜索树的模拟实现 二叉搜索树——查找 二…

东莞网页设计结构图

东莞网页设计结构图是一个网页设计师在设计网站时使用的工具&#xff0c;用来展示网页的布局、内容结构和功能模块等信息。在设计一个网页时&#xff0c;网页设计师通常会首先制作一个网页设计结构图&#xff0c;以便更好地组织和规划网站的内容和功能。东莞网页设计结构图可以…

PFA的特点及焊接方法和应用领域

一、PFA特点&#xff1a; 1、外观半透明&#xff0c;易观察试剂情况&#xff1b; 2、耐高低温&#xff1a;-200&#xff5e;260℃&#xff1b; 3、耐腐蚀&#xff1a;耐强酸、强碱、王水、HF和各种有机溶剂&#xff1b; 4、防污染&#xff1a;本底值低&#xff0c;金属元素…

SpringBoot 整合 Spring Security 、JWT 实现认证、权限控制

​ 博客主页: 南来_北往 系列专栏&#xff1a;Spring Boot实战 前言 Spring Security 和 JWT 实现认证、权限控制是一种在Web应用中保障安全的重要手段。 Spring Security是一个功能强大的身份验证和访问控制框架&#xff0c;它提供了完善的认证机制和方法级的授权功能。…

手机维修--学习笔记(一)

最近觉得手机主板维修比较有意思&#xff0c;观看许多师傅的维修视频&#xff0c;并做笔记如下&#xff1a; 手机主板维修&#xff1a; 【手机电路板怎么修&#xff0c;师傅对着电路图一步一步讲解&#xff0c;看完受益匪浅】https://www.bilibili.com/video/BV13A411v7wL?v…

梯度和反向传播

一.梯度 在机器学习的时候都了解过了&#xff0c;梯度是一个向量&#xff0c;导数变化最快的方向 损失函数&#xff1a; 通过梯度使损失降到最 用ywxb举例也就是使用梯度来更新w的值&#xff0c;ww-学习率*梯度。大于零就减小&#xff0c;反之增大 二.反向传播 就比如搭积木…

【源码+文档+调试讲解】古风生活体验交流网站

摘 要 二十一世纪我们的社会进入了信息时代&#xff0c;信息管理系统的建立&#xff0c;大大提高了人们信息化水平。传统的管理方式对时间、地点的限制太多&#xff0c;而在线管理系统刚好能满足这些需求&#xff0c;在线管理系统突破了传统管理方式的局限性。于是本文针对这一…

24/8/5算法笔记 逻辑回归sigmoid

今日是代码对sigmoid函数的实现和运用 #linear_model线性回归 #名字虽然叫逻辑回归&#xff0c;作用于分类 #分类&#xff1a;类别 #回归&#xff1a;预测 from sklearn.linear_model import LogisticRegression 实现函数 import numpy as np import matplotlib.pyplot as pl…

Linux笔记-3()

目录 一、Linuⅸ实操篇-定时任务调度 二、Linuⅸ实操篇-Linuⅸ磁盘分区、挂载 三、Linux实操篇-网络配置 一、Linuⅸ实操篇-定时任务调度 1 crond任务调度---crontab进行定时任务的设置1.1 概述任务调度&#xff1a;是指系统在某个时间执行的特定的命令或程序。任务调度分类…

【python】OpenCV—Image Colorization

文章目录 1、CIELAB 色彩空间2、作色问题定义3、Caffe 模型4、代码实现——Image5、代码实现——Video6、参考 1、CIELAB 色彩空间 Lab颜色空间&#xff0c;也称为Lab色彩空间或CIELAB色彩空间&#xff0c;是一种基于人类视觉感知特性的颜色模型。它是在1931年国际照明委员会&…

渗透SQL注入

首先打开php: Less-1: 打开浏览器输入网址&#xff0c;进入靶场&#xff1a; 输入?id1查询&#xff1a; 使用order by查询数据表的列数&#xff1a; http://127.0.0.1/sqllab/less-1/?id1 order by 4 -- ​ http://127.0.0.1/sqllab/less-1/?id1 order by 3 -- 由此可得表…

基于paddleocr实现验证码识别——训练数据

一、项目介绍 验证码&#xff08;CAPTCHA&#xff09;用于区分用户是人类还是计算机程序&#xff08;如机器人&#xff09;。这是为了防止各种形式的自动化攻击和滥用。以下是需要验证码识别的几个主要原因&#xff1a; 1. 防止恶意破解密码 攻击者可能会使用自动化程序进行…

数据结构----------贪心算法

什么是贪心算法&#xff1f; 贪心算法&#xff08;Greedy Algorithm&#xff09;是一种在问题求解过程中&#xff0c;每一步都采取当前状态下最优&#xff08;即最有利&#xff09;的选择&#xff0c;从而希望导致最终的全局最优解的算法策略。 贪心算法的核心思想是做选择时&…

【深度学习】DeepSpeed,ZeRO 数据并行的三个阶段是什么?

文章目录 ZeRO实验实验设置DeepSpeed ZeRO Stage-2 实验性能比较进一步优化DeepSpeed ZeRO Stage-3 和 CPU 卸载结论ZeRO ZeRO(Zero Redundancy Optimizer)是一种用于分布式训练的大规模深度学习模型的优化技术。它通过分片模型状态(参数、梯度和优化器状态)来消除数据并行…

Flink异步IO 调用算法总是超时

记录一次使用Flink 异步调用IO 总是超时的bug 注&#xff1a;博主使用的版本就是&#xff1a;<flink.version>1.16.1</flink.version> 起因&#xff1a; 因公司业务需要&#xff0c;使用Flink对数据进行流式处理&#xff0c;具体处理流程就是&#xff0c;从kafka…

PageRank算法与TextRank算法

PageRank PageRank 是一种用于计算网页重要性的算法&#xff0c;其核心思想源自随机浏览模型。这个模型假设一个网络中的用户通过随机点击链接在网页之间跳转&#xff0c;并根据网页的链接结构计算每个网页的重要性。 假设三个网页按以下方式连接&#xff0c;计算每个网页的PR值…

【零基础实战】基于物联网的人工淡水湖养殖系统设计

文章目录 一、前言1.1 项目介绍1.1.1 开发背景1.1.2 项目实现的功能1.1.3 项目硬件模块组成1.1.4 ESP8266工作模式配置 1.2 系统设计方案1.2.1 关键技术与创新点1.2.2 功能需求分析1.2.3 现有技术与市场分析1.2.4 硬件架构设计1.2.5 软件架构设计1.2.6 上位机开发思路 1.3 系统…