zoukankan      html  css  js  c++  java
  • 实现自己的系统调用针对linux-2.6.34【转】

    转自:http://biancheng.dnbcw.net/linux/303362.html

     在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, '', 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 = " ";
        char *menu_line = "state prio static_prio normal_prio pid tgid comm ";
        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! ");
            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, '', 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, '', 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, '', 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, '', 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, '', 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, '', 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, '', 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, '', TMP_DATA_LEN);
            strcpy(tmpdata, " ");
            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中。
  • 相关阅读:
    Perface(TCP/IP 协议族)
    CHAPTER 2 Database Environment
    Chapter 1 Introduction
    2. Instructions: Language of the computer (指令:计算机语言)
    sed命令
    磁盘配额
    外设,镜像
    磁盘及文件系统挂载
    网络客户端工具命令
    TCP协议
  • 原文地址:https://www.cnblogs.com/sky-heaven/p/7060320.html
Copyright © 2011-2022 走看看