免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 22614 | 回复: 92

写了一个内核模块 实现简单的类似ps命令. [复制链接]

论坛徽章:
1
荣誉版主
日期:2011-11-23 16:44:17
发表于 2005-11-22 14:07 |显示全部楼层
内核模块创建在proc文件系统上建立_ps文件.遍例进程内核链表task_struct.将遍例结果存入缓冲区.影射到/proc/_ps文件中.用户态的程序去读取 这个文件.打印显示 当前进程的的pid,ppid 和进程名.


  1. #include <linux/kernel.h>
  2. #include <linux/module.h>
  3. #include <linux/proc_fs.h>
  4. #include <linux/init.h>
  5. #include <linux/sched.h>

  6. MODULE_LICENSE("GPL");
  7. MODULE_AUTHOR("mq110");

  8. static int ps_read(char *page, char **start, off_t offset,int count, int *eof, void *data)  
  9. {
  10.     static char buf[1024*8]={0};
  11.     char tmp[128];
  12.     struct task_struct *p;
  13.    

  14.     if(offset >0)
  15.         return 0;
  16.     memset(buf,0,sizeof(buf));
  17.     read_lock(&tasklist_lock);
  18.     for_each_process(p)   //遍例内核进程链表.
  19.     {
  20.         sprintf(tmp,"%d\t\t%d\t\t\t%s\n",p->pid,p->parent->pid,p->comm);
  21.         strcat(buf,tmp);
  22.         memset(tmp,0,sizeof(tmp));
  23.     }
  24.     read_unlock(&tasklist_lock);
  25.     *start=buf;
  26.     return strlen(buf);
  27. }

  28. static __init int ps_init(void)
  29. {
  30.     struct proc_dir_entry *entry;

  31.     entry = create_proc_entry("_ps", 0444, &proc_root);  //建立/proc/_ps文件.
  32.     if(entry == 0)
  33.     {
  34.         printk(KERN_ERR "create_proc_entry failed!\n");
  35.         return -1;
  36.     }
  37.     entry->mode = S_IFREG | 0444;
  38.     entry->size = 0;
  39.     entry->read_proc = ps_read;
  40.     return 0;
  41. }
  42. static __exit void ps_cleanup(void)
  43. {
  44.     remove_proc_entry("_ps", &proc_root);
  45. }

  46. module_init(ps_init);
  47. module_exit(ps_cleanup);
复制代码


以下是Makefile. TARGET改名成程序名就OK了.

  1. TARGET = 006
  2. obj-m := $(TARGET).o
  3. KERNELDIR=/lib/modules/`uname -r`/build
  4. PWD=`pwd`

  5. default :
  6.    $(MAKE) -C $(KERNELDIR) M=$(PWD) modules

  7. install :
  8.    insmod $(TARGET).ko
  9. uninstall :
  10.    rmmod $(TARGET).ko

  11. clean :
  12.    rm -rf *.o *.mod.c *.ko
复制代码



以下是用户态程序:

  1. #include <stdio.h>
  2. #include <error.h>

  3. int main()
  4. {
  5.     FILE *fp;
  6.     char buf[1024];

  7.     fp=fopen("/proc/_ps","r");
  8.     if(fp==NULL)
  9.     {
  10.         perror("fopen");
  11.         return -1;
  12.     }
  13.     printf("pid\t\tppid\t\t\tcommand\n");
  14.     while(!feof(fp))
  15.     {
  16.         if(fgets(buf,sizeof(buf),fp)!=NULL)
  17.             printf("%s",buf);
  18.     }
  19.     fclose(fp);
  20.     return 0;
  21. }
复制代码


make ;make install 之后 编译用户态程序.
执行结果:
[root@Firewall 006]# ./likeps
pid             ppid                    command
1               0                       init
2               1                       migration/0
3               1                       ksoftirqd/0
4               1                       watchdog/0
5               1                       migration/1
6               1                       ksoftirqd/1
7               1                       watchdog/1
8               1                       migration/2
9               1                       ksoftirqd/2
10              1                       watchdog/2
11              1                       migration/3
12              1                       ksoftirqd/3
13              1                       watchdog/3
14              1                       events/0
15              1                       events/1
16              1                       events/2
17              1                       events/3
18              1                       khelper
19              1                       kthread
24              19                      kacpid
100             19                      kblockd/0
101             19                      kblockd/1
102             19                      kblockd/2
103             19                      kblockd/3
106             19                      khubd
197             19                      pdflush
198             19                      pdflush
199             1                       kswapd0
200             19                      aio/0
201             19                      aio/1
202             19                      aio/2
203             19                      aio/3
288             19                      kseriod
392             1                       kjournald
1224            1                       udevd
1941            1                       kjournald
1944            1                       kjournald
1967            1                       kjournald
2820            1                       syslogd
2824            1                       klogd
2840            1                       sshd
2852            1                       vsftpd
2862            1                       gpm
2882            1                       atd
3184            1                       mingetty
3185            1                       mingetty
3186            1                       mingetty
3187            1                       mingetty
3188            1                       mingetty
3189            1                       mingetty
6819            1                       mysqld_safe
6846            6819                    mysqld
7475            1                       smbd
7476            7475                    smbd
7480            1                       nmbd
19400           2840                    sshd
19404           19400                   bash

[ 本帖最后由 mq110 于 2005-12-29 14:05 编辑 ]

论坛徽章:
0
发表于 2005-11-22 14:55 |显示全部楼层
鼓励

论坛徽章:
0
发表于 2005-11-22 14:58 |显示全部楼层
如果是 kernel-2.4 应该如何写 Makefile 呢?
如果全部编入内核,没有动态加载模块,应该如何处理呢?

论坛徽章:
1
荣誉版主
日期:2011-11-23 16:44:17
发表于 2005-11-22 15:03 |显示全部楼层
原帖由 platinum 于 2005-11-22 14:58 发表
如果是 kernel-2.4 应该如何写 Makefile 呢?
如果全部编入内核,没有动态加载模块,应该如何处理呢?


我现在没2.4内核的机器了.

那位有2.4的帮写一个

>>如果全部编入内核,没有动态加载模块,应该如何处理呢?

我只是拿 这个练练手. 顺便也给后人学习建立/proc文件和遍例内核进程链表留下点什么.呵呵.~  以前看过ps命令的源代码.有些实现 是遍例/proc目录下各个目录的文件 来实现的.

[ 本帖最后由 mq110 于 2005-11-22 15:07 编辑 ]

论坛徽章:
0
发表于 2005-11-22 15:19 |显示全部楼层
mq110兄,写的不错

一个小问题,for_each_process时,要加读锁的。

read_lock(&tasklist_lock);
…………
read_unlock(&tasklist_lock);

否则在SMP机器上容易出问题

论坛徽章:
1
荣誉版主
日期:2011-11-23 16:44:17
发表于 2005-11-22 15:21 |显示全部楼层
原帖由 albcamus 于 2005-11-22 15:19 发表
mq110兄,写的不错

一个小问题,for_each_process时,要加读锁的。

read_lock(&tasklist_lock);
…………
read_unlock(&tasklist_lock);

否则在SMP机器上容易出问题


原来如此。我马上改过来.
初写内核模块 考虑的不够周全.

论坛徽章:
1
荣誉版主
日期:2011-11-23 16:44:17
发表于 2005-11-22 15:22 |显示全部楼层
要上课了.回来再请教al*兄.

论坛徽章:
0
发表于 2005-11-22 16:16 |显示全部楼层
这个讨论真不错 ^_^

论坛徽章:
0
发表于 2005-11-22 16:45 |显示全部楼层
得向LZ学习。。。以LZ现在的水准,出去工作绝对没问题。。。我相信工资也是不会低的。。

论坛徽章:
1
荣誉版主
日期:2011-11-23 16:44:17
发表于 2005-11-22 18:19 |显示全部楼层
下课了 呵呵.
读锁加上了. al*兄帮忙看看还有问题吗?
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP