转 Linux内核 Ps模块
ricky_proc.c源码:
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/proc_fs.h>
#include <linux/thread_info.h>
#include <linux/list.h>
#include <linux/sched.h>
#define MODULE_VERSION "1.0"
#define MODULE_NAME "ricky_proc_info_final"
#define P_MAX_LEN 30
#define ARRAYMAX 4096
static struct proc_dir_entry *ricky_file, *ricky_dir;
static char c[ARRAYMAX];
static int proc_read_info(char *page,char **start,off_t off,int count, int *eof,void *data)
{
int len=0;
char *c = (char *)ricky_file->data;
len=sprintf(page,"%s\n",c);
return len;
}
static int __init ricky_info_init(void)
{
//get_current() is defined to current
//so we could get a task by "current"
struct task_struct *task_c;
task_c = current;
struct task_struct *p;
struct list_head *pos;
int count=0;
int rv=0;
//create proc directory
ricky_dir = proc_mkdir(MODULE_NAME, NULL);
if(ricky_dir==NULL){
rv=-ENOMEM;
goto out;
}
ricky_dir->owner = THIS_MODULE;
//create proc file
ricky_file=create_proc_entry("rickyps",0644,ricky_dir);
if(ricky_file==NULL){
rv=-ENOMEM;
goto no_rickyps;
}
//traversal of task_list
int length=0;
int l=0;
list_for_each(pos, &task_c->tasks){
//get the list_entry
p=list_entry(pos, struct task_struct, tasks);
count++;
if(count==1){
length+=sprintf(c+l,"No.\tPid\tCMD\n%d\t%d\t%s\n",count,p->pid,p->comm);
l=l+length;
}
else{
length=sprintf(c+l,"%d\t%d\t%s\n",count,p->pid,p->comm);
l=l+length;
}
}
printk(KERN_INFO "Total number of processes is: %d\n",count);
length=sprintf(c+l,"Total number of processes is %d\n",count);
l=l+length;
//link proc file
ricky_file->data=c;
ricky_file->read_proc=proc_read_info;
ricky_file->owner=THIS_MODULE;
printk(KERN_INFO "%s %s initialized.\n", MODULE_NAME, MODULE_VERSION);
return 0;
no_rickyps:
remove_proc_entry("rickyps",ricky_dir);
out:
return rv;
}
static void __exit ricky_info_exit(void)
{
remove_proc_entry("rickyps",ricky_dir);
remove_proc_entry(MODULE_NAME,NULL);
printk(KERN_INFO "%s %s has been removed.\n",MODULE_NAME,MODULE_VERSION);
}
MODULE_AUTHOR("Ricky Song");
MODULE_LICENSE("GPL");
module_init(ricky_info_init);
module_exit(ricky_info_exit);
Makefile文件:
obj-m := ricky_proc.o
all:
make -C /lib/modules/$(shell uname -r)/build M=$(shell pwd) modules
clean:
rm -rf *.o *.mod.c *.ko Modules.symvers
内核模块创建在proc文件系统上建立_ps文件.遍例进程内核链表task_struct.将遍例结果存入缓冲区.影射到/proc/_ps文件中.用户态的程序去读取 这个文件.打印显示 当前进程的的pid,ppid 和进程名.
#include <linux/module.h>
#include <linux/proc_fs.h>
#include <linux/init.h>
#include <linux/sched.h>
MODULE_LICENSE("GPL");
MODULE_AUTHOR("mq110");
static int ps_read(char *page, char **start, off_t offset,int count, int *eof, void *data)
{
static char buf[1024*8]={0};
char tmp[128];
struct task_struct *p;
if(offset >0)
return 0;
memset(buf,0,sizeof(buf));
read_lock(&tasklist_lock);
for_each_process(p) //遍例内核进程链表.
{
sprintf(tmp,"%d\t\t%d\t\t\t%s\n",p->pid,p->parent->pid,p->comm);
strcat(buf,tmp);
memset(tmp,0,sizeof(tmp));
}
read_unlock(&tasklist_lock);
*start=buf;
return strlen(buf);
}
static __init int ps_init(void)
{
struct proc_dir_entry *entry;
entry = create_proc_entry("_ps", 0444, &proc_root); //建立/proc/_ps文件.
if(entry == 0)
{
printk(KERN_ERR "create_proc_entry failed!\n");
return -1;
}
entry->mode = S_IFREG | 0444;
entry->size = 0;
entry->read_proc = ps_read;
return 0;
}
static __exit void ps_cleanup(void)
{
remove_proc_entry("_ps", &proc_root);
}
module_init(ps_init);
module_exit(ps_cleanup);
以下是Makefile. TARGET改名成程序名就OK了.
obj-m := $(TARGET).o
KERNELDIR=/lib/modules/`uname -r`/build
PWD=`pwd`
default :
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules
install :
insmod $(TARGET).ko
uninstall :
rmmod $(TARGET).ko
clean :
rm -rf *.o *.mod.c *.ko
以下是用户态程序:
#include <error.h>
int main()
{
FILE *fp;
char buf[1024];
fp=fopen("/proc/_ps","r");
if(fp==NULL)
{
perror("fopen");
return -1;
}
printf("pid\t\tppid\t\t\tcommand\n");
while(!feof(fp))
{
if(fgets(buf,sizeof(buf),fp)!=NULL)
printf("%s",buf);
}
fclose(fp);
return 0;
}
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
------------------------------------------------------------
|
user.c
|
Makefile:
|
可以对ps_read做如下改进
|
for_each_process(p)遍历每一个进程
|