文章正文
linux内核编程之sys接口以及workqueue
sys接口顾名思义/sys目录下的接口,linux系统是一个一切都是文件的系统,通过sys接口可以与内核的模块进行互动
下面是默认sys目录下的内容
下面通过编程可以实现我们自己的模块以及sys接口。
实现sys接口并不难,只要会使用几个api就可以了,下面以一个实际的例子说明
sysfs.c
#include<linux/module.h> #include<linux/kernel.h> #include<linux/init.h> #include<linux/interrupt.h> #include<linux/sched.h> #include<linux/workqueue.h> #include<linux/sysfs.h> #include<linux/string.h> #include<linux/device.h> #include<linux/kobject.h> #define zachary_name "zachary" MODULE_AUTHOR("zachary"); MODULE_LICENSE("GPL"); static int TimerIntrpt = 0; static int finished = 0; static int run=1,interval=1; static void intrpt_routine(void *); static struct workqueue_struct *keyqueue; static struct delayed_work Task; static void intrpt_routine(void *irrelevant){ TimerIntrpt++; if(finished == 0){ queue_delayed_work(keyqueue,&Task,interval); } } static ssize_t run_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf){ return sprintf(buf,"%d\n",run); } static ssize_t run_store(struct file *file, struct kobj_attribute *attr, const char *buf, size_t length){ sscanf(buf,"%du",&run); if(run&&finished){ finished=0; queue_delayed_work(keyqueue,&Task,20); }else if(run==0){ finished=1; cancel_delayed_work(&Task); flush_workqueue(keyqueue); } return length; } static ssize_t interval_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf){ return sprintf(buf,"%d\n",TimerIntrpt); } static ssize_t interval_store(struct file *file, struct kobj_attribute *attr, const char *buf, size_t length){ float hz; sscanf(buf,"%fu",&hz); interval = 1000/hz; printk("msg:%f\n",interval); return length; } static struct kobj_attribute run_attribute = __ATTR(run,0666,run_show,run_store); static struct kobj_attribute interval_attribute = __ATTR(interval,0666,interval_show,interval_store); static struct kobject *run_kobj; static int init(void){ int runval,interval_val; printk("<0>" "init_ok\n"); run_kobj = kobject_create_and_add(zachary_name,NULL); if(!run_kobj){ return -ENOMEM; } runval = sysfs_create_file(run_kobj,&run_attribute); interval_val = sysfs_create_file(run_kobj,&interval_attribute); if(runval && interval_val){ kobject_put(run_kobj); } keyqueue = create_workqueue("keyqueue"); INIT_DELAYED_WORK(&Task,intrpt_routine); queue_delayed_work(keyqueue,&Task,interval); return runval; } static void exit(void) { printk("<0>" "Bey\n"); kobject_put(run_kobj); finished = 1; cancel_delayed_work(&Task); flush_workqueue(keyqueue); destroy_workqueue(keyqueue); } module_init(init); module_exit(exit);
Makefile如下:
obj-m := sysfs.o
KERNEL_DIR := /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)
all:
make -C $(KERNEL_DIR) SUBDIRS=$(PWD) modules
clean:
rm *.o *.ko *.mod.c
如上代码所示,实现sys接口只需要3个函数,一个结构体
sysfs_create_file xxx_show xxx_store xxx = __ATTR(run,0666,run_show,run_store);
__ATTR是一个宏定义,实际的作用是申明一个结构体。
另外,上面的例子实现了可以延时的workqueue,总体来说,简单的对照就可以写出想要的效果。
Dec. 24, 2015, 11:04 p.m. 作者:zachary 分类:Linux相关 阅读(1822) 评论(0)
评论列表:
评论: