fasync实现通过文件修改代码中的变量值大小
创始人
2025-05-28 02:29:06
0

fasync实现通过文件修改代码中的变量值大小


文章目录

  • fasync实现通过文件修改代码中的变量值大小
  • 1.fasync_flag.c
  • 2.app.c
  • 3.Makefile
  • 结果
    • 1.编译
    • 2.在根文件系统下创建fasync目录
    • 3.复制模块文件和应用程序到根文件目录下
    • 4.安装模块
    • 5.安装后结果
    • 6.通过文件修改变量flag的值


下面用一个具体的例子来展示设备驱动程序如何实现fasync方法,以及应用程序如何得到来自设备驱动程序的异步通知。这个例了同时也展示了sysfs文件系统在驱动程序中的用法,以及通过Linux设各模型来创建设备节点及其他一些特性(这个看起来很简单的内核模块其实体现了设备驱动程序中一些比较重要且典型的特征)。

首先是设备驱动程序的代码,在代码中,我们将Linux设备模型中的一些概念融入其中(本书第9章会详细讨论Linux的设备驱动模型,不过读者可以在这里先热热身),这样我们可以动态创建一个设备节点而无须再手动地使用mknod命令,同时代码中还创建了一个sysfs文件接口,这使得我们可以直接操控设备驱动程序中的一些数据而不必采用ioctl的方式·也许这就是设备驱动模型给我们带来的好处吧。

1.fasync_flag.c

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include #include 
#include static unsigned long flag = 0;
/*设备struct*/
struct led_struct
{dev_t led_dev;struct cdev led_cdev;struct class *led_class;struct device *led_device;struct fasync_struct *sigio_list;struct device_node *led_nd;};
struct led_struct led_struct;
ssize_t read_flag(struct device *dev,struct device_attribute *attr,char *buf){size_t count = 0;count += sprintf(&buf[count],"%lu\n",flag);return count;
}ssize_t write_flag(struct device * dev,struct device_attribute *attr,char *buf,size_t count){flag = buf[0] - '0';//给所有以FASYNC标志调用fcntl的应用程序发信号kill_fasync(&led_struct.sigio_list,SIGIO,POLL_IN);return count;
}
struct device_attribute flag_attr = __ATTR(flag,S_IRUGO | S_IWUSR,read_flag,write_flag);int led_open(struct inode *inode, struct file *filp)//打开led
{printk("_____%s_____\n",__FUNCTION__);return 0;
}int led_fasync (int fd, struct file *filp, int onflag){//将需要通知的迸程加入sigio_list链表或者从链表中移除return fasync_helper(fd, filp, onflag, &led_struct.sigio_list);
}
static struct file_operations led_ops = {.owner = THIS_MODULE,.open = led_open,        .fasync = led_fasync,
};
static int __init led_init(void)
{    int ret = 0;//    1.分配设备号alloc_chrdev_region(&led_struct.led_dev, 0, 1, "my_led");//2.创造cdev对象和file_operation,然后cdev_init初始化cdev_init(&led_struct.led_cdev, &led_ops);//3.cdev_add将cdev对象注册进入内核cdev_add(&led_struct.led_cdev, led_struct.led_dev, 1);//4.创造class与deviceled_struct.led_class =  class_create(THIS_MODULE, "led_class");led_struct.led_device=device_create(led_struct.led_class, NULL, led_struct.led_dev, NULL, "led");//在文件系统中创建一个名为"flag的文件ret = device_create_file(led_struct.led_device,&flag_attr);printk("flag = %d\n",flag);return ret;
}static void __exit led_exit(void)
{printk("flag = %d\n",flag);device_destroy(led_struct.led_class, led_struct.led_dev);class_destroy(led_struct.led_class);cdev_del(&led_struct.led_cdev);unregister_chrdev_region(led_struct.led_dev, 1);
}module_init(led_init);
module_exit(led_exit);
MODULE_LICENSE("GPL");

2.app.c

应用程序:app.c

#include "stdio.h"
#include "unistd.h"
#include "sys/types.h"
#include "sys/stat.h"
#include "sys/ioctl.h"
#include "fcntl.h"
#include "stdlib.h"
#include "string.h"
#include 
#include 
#include 
#include 
#include int fd_tty,fd_led,fd_iic;
static unsigned long eflag;static void sigio_handler(int sigio){eflag = 0;
}static int block_sigio(void){sigset_t set,old;int ret;sigisemptyset(&set);sigaddset(&set,SIGIO);sigprocmask(SIG_BLOCK,&set,&old);ret = sigismember(&old, SIGIO);return ret;
}static void unblock_sigio(int blocked){sigset_t set;if(!blocked){sigisemptyset(&set);sigaddset(&set,SIGIO);sigprocmask(SIG_UNBLOCK,&set,NULL);}
}
int main(int argc, char *argv[])
{int fd;struct sigaction sigact,oldact;int oflag;int blocked;blocked = block_sigio();sigisemptyset(&sigact.sa_mask);sigaddset(&sigact.sa_mask,SIGIO);sigact.sa_flags = 0;sigact.sa_handler = sigio_handler;if(sigaction(SIGIO,&sigact,&oldact) < 0){printf("sigaction failed!\n");unblock_sigio(blocked);return -1;}unblock_sigio(blocked);    fd = ("/dev/led",O_RDWR);if(fd>=0){fcntl(fd_led,F_SETOWN,getpid());oflag = fcntl(fd_led,F_GETFL);fcntl(fd_led,F_SETFL,oflag | FASYNC);printf("do everything you want until we get signal..\n");while(eflag);   close(fd);}return 0;         
}

3.Makefile

#make 编译项目
#make file 在存放.ko文件目录中创建对应项目的目录
#make install 将*.ko及其应用测试文件移动到根文件中# 1. 使用不同的开发板内核时, 一定要修改KERN_DIR
# 2. KERN_DIR中的内核要事先配置、编译, 为了能编译内核, 要先设置下列环境变量:
# 2.1 ARCH,          比如: export ARCH=arm64
# 2.2 CROSS_COMPILE, 比如: export CROSS_COMPILE=aarch64-linux-gnu-
# 2.3 PATH,          比如: export PATH=$PATH:/home/book/100ask_roc-rk3399-pc/ToolChain-6.3.1/gcc-linaro-6.3.1-2017.05-x86_64_aarch64-linux-gnu/bin 
# 注意: 不同的开发板不同的编译器上述3个环境变量不一定相同,
#       请参考各开发板的高级用户使用手册# ROOTFS_DIR 根文件系统中存放 *.ko文件所在目录
# PROJECT_NAME 在存放.ko文件目录中创建对应项目的目录
# DRIVER_NAME 项目中需要编译出.ko来的驱动
# APP_NAME 项目中的应用测试文件#make 编译项目
#make file 在存放.ko文件目录中创建对应项目的目录
#make install 将*.ko及其应用测试文件移动到根文件中KERN_DIR = /home/alientek/linux/IMX6ULL/linux/temp/linux-imx-rel_imx_4.1.15_2.1.0_ga_alientek
ROOTFS_DIR = /home/alientek/linux/nfs/rootfs/experiment
#项目名字
PROJECT_NAME = fasync
#各驱动名字,ko
DRIVER_NAME1 = fasync_flag
DRIVER_NAME2 = 
#app名字
APP_NAME = app
all:make -C $(KERN_DIR) M=`pwd` modules $(CROSS_COMPILE)arm-linux-gnueabihf-gcc -o $(APP_NAME) $(APP_NAME).c clean:make -C $(KERN_DIR) M=`pwd` modules cleanrm -rf modules.orderrm -f $(APP_NAME)
file:mkdir $(ROOTFS_DIR)/$(PROJECT_NAME)
install:cp *.ko $(ROOTFS_DIR)/$(PROJECT_NAME)cp $(APP_NAME) $(ROOTFS_DIR)/$(PROJECT_NAME)
# 参考内核源码drivers/char/ipmi/Makefile
# 要想把a.c, b.c编译成ab.ko, 可以这样指定:
# ab-y := a.o b.o
# obj-m += ab.oobj-m += $(DRIVER_NAME1).o

结果

1.编译

make

在这里插入图片描述

2.在根文件系统下创建fasync目录

sudo make file

3.复制模块文件和应用程序到根文件目录下

sudo make install

在这里插入图片描述

4.安装模块

insmod fasync_flag.ko

5.安装后结果

在这里插入图片描述
变量flag此时为0,另外在目录**/sys/devices/virtual/led_class/led** 下有一个flag文件,我们可以通过修改这个flag文件来修改变量flag的值
在这里插入图片描述

6.通过文件修改变量flag的值

echo 5 > flag

在这里插入图片描述
然后卸载模块查看变量的大小

rmmod fasync_flag.ko

在这里插入图片描述

变量flag的值最终被成功修改

相关内容

热门资讯

监控摄像头接入GB28181平... 流程简介将监控摄像头的视频在网站和APP中直播,要解决的几个问题是:1&...
Windows10添加群晖磁盘... 在使用群晖NAS时,我们需要通过本地映射的方式把NAS映射成本地的一块磁盘使用。 通过...
protocol buffer... 目录 目录 什么是protocol buffer 1.protobuf 1.1安装  1.2使用...
Fluent中创建监测点 1 概述某些仿真问题,需要创建监测点,用于获取空间定点的数据࿰...
educoder数据结构与算法...                                                   ...
MySQL下载和安装(Wind... 前言:刚换了一台电脑,里面所有东西都需要重新配置,习惯了所...
MFC文件操作  MFC提供了一个文件操作的基类CFile,这个类提供了一个没有缓存的二进制格式的磁盘...
在Word、WPS中插入AxM... 引言 我最近需要写一些文章,在排版时发现AxMath插入的公式竟然会导致行间距异常&#...
有效的括号 一、题目 给定一个只包括 '(',')','{','}'...
【Ctfer训练计划】——(三... 作者名:Demo不是emo  主页面链接:主页传送门 创作初心ÿ...