Linux内核驱动入门 proc文件读写

前言

中文互联网真的依托矢
就一个简简单单的内核驱动,不少人居然还设置了关注可见,甚至是VIP专栏,醉了
大部分入门的内核驱动都是字符设备的hello world,那个文章一抓一大把,不过相比用字符驱动输出helloworld,我觉得还是proc更简单

源码和Makefile

arcoproc.c(和Makefile中的obj保持一致)

这里创建了两个proc文件fa和fb, 以fa为例 调用链如下:

arcoproc_init
	arco_init_proc
		create_fa
			.open=fa_open
			.read=fa_read

fa是自己实现的read:在第n+1次尝试读时返回0强制结束(否则用cat读取会无限输出)
fb通过seq_file系列函数实现了open,读函数为seq_read

#include<linux/init.h>
#include<linux/module.h>
#include<linux/kernel.h>
#include<linux/proc_fs.h>  
#include<linux/seq_file.h> // seq_read
#include<linux/string.h>
#include <linux/uaccess.h> // copy_to_user

#define FAName "fa"
#define FBName "fb"

// proc file and ops
struct procfileops{
    struct proc_dir_entry* file;
    struct file_operations ops;
};

struct kirin {
    struct proc_dir_entry* procfs;
    struct procfileops fa;
    struct procfileops fb;
};
struct kirin kirin7;

int arcoproc_flag = 0;
int fa_flag = 0;
int fb_flag = 0;
int fa_read_flag = 0;

// fa funcs
int fa_open(struct inode *inode, struct file *filp) {
    return 0;
}
int fa_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos) {
    fa_read_flag = ~fa_read_flag;
    if (!fa_read_flag) return 0;
    char str[32] = "arco say: this is fa\n";
    int len = strlen(str);
    if (copy_to_user(buf, str, len)) {
        return -1;
    }
    *ppos += len;
    return len;
}
int create_fa(void) {
    printk("arcoproc create fa~\n");
    kirin7.fa.ops.open = fa_open;
    kirin7.fa.ops.read = fa_read;
    kirin7.fa.file = proc_create(FAName, 0444, kirin7.procfs, &kirin7.fa.ops);
    if (kirin7.fa.file == NULL) {
        printk("arco create fa failed!\n");
        return -1;
    }
    fa_flag = 1;
    return 0;
}

// fb funcs
int single_fb_open(struct seq_file* m, void* v) {
    char str[32] = "arco say: this is fb\n";
    seq_printf(m, str);
    return 0;
}
int fb_open(struct inode *inode, struct file *filp) {
    return single_open(filp, single_fb_open, NULL);
}
int create_fb(void) {
    printk("arcoproc create fb~\n");
    kirin7.fb.ops.open = fb_open;
    kirin7.fb.ops.read = seq_read;
    kirin7.fb.file = proc_create(FBName, 0444, kirin7.procfs, &kirin7.fb.ops);
    if (kirin7.fb.file == NULL) {
        printk("arco create fb failed!\n");
        return -1;
    }
    fb_flag = 1;
    return 0;
}


int arco_init_proc(void) {
    printk("arco init proc~\n");
    kirin7.procfs = proc_mkdir("arcoproc", NULL);
    if (kirin7.procfs == NULL) {
        printk("arco init proc dir failed!\n");
        return -1;
    }
    create_fa();
    create_fb();
    return 0;
}

static int __init arcoproc_init(void) {
    printk("arcoproc init~\n");
    arco_init_proc();
    return 0;
}

static void __exit arcoproc_exit(void) {
    proc_remove(kirin7.procfs);
    if (fa_flag) proc_remove(kirin7.fa.file);
    if (fb_flag) proc_remove(kirin7.fb.file);
    printk("arco say: bye~\n");
}

module_init(arcoproc_init);
module_exit(arcoproc_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("ARCO");
MODULE_DESCRIPTION("arco proc test");


Makefile

KDIR := /home/arco/kernel/linux-imx
obj-m=arcoproc.o
PWD=$(shell pwd)
all:
	make -C $(KDIR) M=$(PWD) modules
clean:
	make -C $(KDIR) M=$(PWD) clean

编译运行

编译 上传

make clean
make
if [ $? -eq 0 ];then
  scpauto arcoproc.ko root@192.168.0.30:/home/arco/drivers 123456
fi

上述的scpauto是我用expect封装的一个脚本,功能是自动填充ssh的密码
基于expect的ssh自动输入密码脚本

运行

这里是用minicom连接的串口,printk直接打印出来了
可以看到,在/proc目录下创建了arcoproc目录,然后在其下生成了fa和fb两个文件

insmod #插入驱动
rmmode #移除驱动

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值