Chinaunix首页 | 论坛 | 博客
  • 博客访问: 939687
  • 博文数量: 146
  • 博客积分: 3321
  • 博客等级: 中校
  • 技术积分: 1523
  • 用 户 组: 普通用户
  • 注册时间: 2008-08-29 10:32
文章分类

全部博文(146)

文章存档

2014年(2)

2013年(5)

2012年(4)

2011年(6)

2010年(30)

2009年(75)

2008年(24)

分类: LINUX

2010-06-27 21:02:34

    在linux下实现自己的系统调用。主要功能是:遍历系统的进程,并将相关的进程信息存放在自己定义的结构体中,同时编写系统调用,实现内核数据向用户空间的文件中写入。
首先实现相关的系统调用:
1.修改系统调用表:
在目录/usr/src/linux-2.6.33.1/arch/x86/kernel
修改文件:syscall_table_32.S 在文件的末尾处添加自己的系统调用表项。
如下:
        .long sys_rt_tgsigqueueinfo /* 335 */
.long sys_perf_event_open
.long sys_recvmmsg
.long sys_sayhello
        .long sys_getdata
        .long sys_datawrite
        .long sys_dataflush
其中绿色部分是上一个简单的系统调用测试。下面3个红色部分的是我现在要实现的从内核部分向用户空间写文件。

2.添加系统调用号。
在目录/usr/src/linux-2.6.33.1/arch/x86/include/asm/
修改文件unistd_32.h文件,在文件中添加自己的系统调用号。
如下:
#define __NR_perf_event_open 336
#define __NR_recvmmsg 337
#define __NR_syahello 338
#define  __NR_getdata                 339
#define  __NR_datawrite               340
#define  __NR_dataflush               341
同时修改接下来的定义:
#define NR_syscalls                   342          //这个表示的当前系统调用的总数
其中绿色部分是上一个简单的系统调用测试。下面3个红色的是我们当前需要关心的。

3.编写系统调用的处理函数:
原则上你可一在内核文件的任何位置添加你的处理函数。我这里选择在kernel目录下新建一个自己的C文件。
get_data.c
这就需要修改相关的Makefile文件。修改get_data.c所在的目录下的Makefile文件
找到大概16行,添加你的编译目标
如下(红色部分为自己添加的):
obj-y += groups.o
obj-y += get_data.o

get_data.c文件的内容:

#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/mm.h>
#include <linux/sched.h>
#include <asm/uaccess.h>
#include <linux/slab.h>

#define TASK_COMM_LEN 16
#define TMP_DATA_LEN 50

typedef struct my_task_struct {
    
volatile long state;
    
int prio, static_prio, normal_prio;
    
pid_t pid;
    
pid_t tgid;
    
char comm[TASK_COMM_LEN];
    
struct my_task_struct *next;
}my_struct_t, *my_struct_p;

my_struct_p get_data
(void)
{
    my_struct_p p
, head, h;
    
struct task_struct *task = NULL;

    head
= (my_struct_p)kmalloc(sizeof(my_struct_t), GFP_ATOMIC);
    head
->next = NULL;
    h
= head;

    for_each_process
(task) {
        p
= (my_struct_p)kmalloc(sizeof(my_struct_t), GFP_ATOMIC);

        p
->state = task->state;
        p
->prio = task->prio;
        p
->static_prio = task->static_prio;
        p
->normal_prio = task->normal_prio;
        p
->pid = task->pid;
        p
->tgid = task->tgid;

        
memset(p->comm, '\0', sizeof(p->comm));
        
strncpy(p->comm, task->comm, TASK_COMM_LEN-1);

        p
->next = h->next;
        h
->next = p;
        h
= p;
    
}
    
return head;
}

int filewrite(const char * filename, my_struct_p head)
{
    
struct file *filp;
    mm_segment_t fs
;
    my_struct_p data
;
    
char *change_line = "\t";
    
char *menu_line = "state\tprio\tstatic_prio\tnormal_prio\tpid\ttgid\tcomm\n";
    
char tmpdata[TMP_DATA_LEN];


    data
= head->next;
    filp
= filp_open(filename, O_RDWR|O_APPEND|O_CREAT, 0644);
    
if(IS_ERR(filp)) {
        printk
("open error!\n");
        
return 1;
    
}
    fs
= get_fs();
    set_fs
(KERNEL_DS);
    filp
->f_op->write(filp, menu_line, strlen(menu_line), &filp->f_pos);

    
while(NULL != data) {
        
memset(tmpdata, '\0', TMP_DATA_LEN);
        snprintf
(tmpdata, sizeof(data->state), "%ld", data->state);
        
strcat(tmpdata, change_line);
        filp
->f_op->write(filp, tmpdata, strlen(tmpdata), &filp->f_pos);

        
memset(tmpdata, '\0', TMP_DATA_LEN);
        snprintf
(tmpdata, sizeof(data->prio), "%d", data->prio);
        
strcat(tmpdata, change_line);
        filp
->f_op->write(filp, tmpdata, strlen(tmpdata), &filp->f_pos);

        
memset(tmpdata, '\0', TMP_DATA_LEN);
        snprintf
(tmpdata, sizeof(data->static_prio), "%d", data->static_prio);
        
strcat(tmpdata, change_line);
        filp
->f_op->write(filp, tmpdata, strlen(tmpdata), &filp->f_pos);

        
memset(tmpdata, '\0', TMP_DATA_LEN);
        snprintf
(tmpdata, sizeof(data->normal_prio), "%d", data->normal_prio);
        
strcat(tmpdata, change_line);
        filp
->f_op->write(filp, tmpdata, strlen(tmpdata), &filp->f_pos);

        
memset(tmpdata, '\0', TMP_DATA_LEN);
        snprintf
(tmpdata, sizeof(data->pid), "%d", data->pid);
        
strcat(tmpdata, change_line);
        filp
->f_op->write(filp, tmpdata, strlen(tmpdata), &filp->f_pos);

        
memset(tmpdata, '\0', TMP_DATA_LEN);
        snprintf
(tmpdata, sizeof(data->tgid), "%d", data->tgid);
        
strcat(tmpdata, change_line);
        filp
->f_op->write(filp, tmpdata, strlen(tmpdata), &filp->f_pos);

        
memset(tmpdata, '\0', TMP_DATA_LEN);
        snprintf
(tmpdata, sizeof(data->comm), "%s", data->comm);
        
strcat(tmpdata, change_line);
        filp
->f_op->write(filp, tmpdata, strlen(tmpdata), &filp->f_pos);
        
        
memset(tmpdata, '\0', TMP_DATA_LEN);
        
strcpy(tmpdata, "\n");
        filp
->f_op->write(filp, tmpdata, strlen(tmpdata), &filp->f_pos);

        data
= data->next;
    
}
    set_fs
(fs);
    filp_close
(filp, NULL);
    
return 0;
}

int data_flush(my_struct_p head)
{
    my_struct_p data
;
    data
= head;
    
while(NULL != data) {
        head
= head->next;
        kfree
(data);
        data
= head;
    
}
    
return 0;
}

asmlinkage my_struct_p sys_getdata
(void)
{
    my_struct_p res
;
    res
= get_data();
    
return res;
}

asmlinkage
int sys_datawrite(const char *filename, my_struct_p head)
{
    
return filewrite(filename, head);
}

asmlinkage
int sys_dataflush(my_struct_p head)
{
    
return data_flush(head);
}


用户空间测试程序:test.c


#include <asm/unistd.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/syscall.h>
#include <stdlib.h>
#include <string.h>

#define SYS_SAYHELLO 338
#define SYS_GETDATA 339
#define SYS_FILEWRITE 340
#define SYS_DATAFLUSH 341

struct my_struct {

    
volatile long state;
    
int prio, static_prio, normal_prio;
    
pid_t pid;
    
pid_t tgid;
    
char comm[16];
    
struct my_struct *next;
};

int main(void)
{
    
struct my_struct * data;
    
    data
= syscall(SYS_GETDATA);
    syscall
(SYS_FILEWRITE, "file", data);
    syscall(SYS_DATAFLUSH, data)
    
return 0;
}
 


对test.c编译运行之后在当前目录下应该可以看到打印出的进程信息在文件file中。

阅读(1891) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~