文章正文
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相关 阅读(2262) 评论(0)
评论列表:
评论: