目录
PS:博客只是提供一个简要的思路,互相学习。
显示当前进程的pid和父进程的pid,主要考察如何获取当前进程的task_struct,并通过task结构体获取指定namespace空间的pid。
图1.代码分析流程
从最顶层开始,一层层往下剖析,我们的目的要获得当前进程的pid,所以我们首先需要获得我们当前的一个task结构体,通过linux中设置的current宏,我们很轻易的可以获取当前进程的task_struct,为了获取指定pid namespace空间的pid,我们还需要获取指定的pid_namespace *ns,然后通过内核函数pid_nr_ns()获取到指定ns的pid即可。
系统调用部分代码:
SYSCALL_DEFINE4(promise,int*,nr,int*,pnr,int*,level,int*,p_level)
{
enum pid_type type=PIDTYPE_PID;
struct pid_namespace *ns = NULL;
struct pid_namespace *pns = NULL;
struct task_struct *tsk = current;
struct task_struct *p_tsk = tsk->parent;
int crt_pid=0,crt_ppid=0;
int crt_level=0,pcrt_level=0;
//rcu保护机制
rcu_read_lock();
//tsk
ns = task_active_pid_ns(tsk);
crt_level=ns->level;
//根据task找到对应的ns
if (likely(pid_alive(tsk)))
{
//get tgid
tsk = tsk->group_leader;
//pid_nr_ns得到的是指定ns的pid
crt_pid = (int)pid_nr_ns(rcu_dereference(tsk->pids[type].pid), ns);
}
//parent tsk
pns=task_active_pid_ns(p_tsk);
pcrt_level=pns->level;
if (likely(pid_alive(p_tsk)))
{
p_tsk = p_tsk->group_leader;
crt_ppid = (int)pid_nr_ns(rcu_dereference(p_tsk->pids[type].pid), pns);
}
rcu_read_unlock();
//copy_to_user()
copy_to_user(nr,&crt_pid,sizeof(crt_pid));
copy_to_user(pnr,&crt_ppid,sizeof(crt_ppid));
copy_to_user(level,&crt_level,sizeof(crt_ppid));
copy_to_user(p_level,&pcrt_level,sizeof(crt_ppid));
return 0;
}
test.c
#include <stdio.h>
#include <unistd.h>
#include <sys/syscall.h>
int main()
{
int pid,ppid,level,p_level;
syscall(292,&pid,&ppid,&level,&p_level);
printf("ns_level:%-5d pid:%-5d p_level:%-5d ppid:%-5d\n",level,pid,p_level,ppid);
while(1);
return 0;
}
1.对内核函数传参传入nr和pnr时,想在内核函数中直接将其值修改,但是运行后失败,查询后是发现内核空间和用户空间不能直接互访,所以必须使用copy_to_user()函数来在内核函数内改变用户程序中传入的参数。
2.系统在reboot的时候直接内核崩坏,服务器无法正常使用,只能强制重装系统,没法复现,但猜测是在内核进行make的过程中出现了某个error没有重视,强行进行reboot所导致。
3.最开始使用的时候,没有考虑到内核内不能调用系统调用,以为简单的在系统调用函数内直接使用getpid()就能实现,试了一番,查询后才知道系统调用只能调用内核API。
4.在代码实现的一开始,选择的是直接去返回当前进程的pid,但是后面看了getpid函数后,发现其传入的type是一个tgid,因为linux没有严格的线程概率,所有一个进程里面可能有多个线程有其相对的pid,如果想返回主要这个进程的pid,就应该返回group_leader的pid,也就是实际是得到了tgid。
1. Linux中的RCU机制[一] - 原理与使用方法[EB/OL]. []. https://zhuanlan.zhihu.com/p/89439043.
2. Linux内核中的RCU[EB/OL]. []. https://zhuanlan.zhihu.com/p/67520807.
3. rcu 机制简介[EB/OL]. []. https://zhuanlan.zhihu.com/p/113999842.
4. linux内核命名空间[EB/OL]. []. https://zhuanlan.zhihu.com/p/136404837.
5. pid namespace详细解读[EB/OL]. []. https://tinylab.org/pid-namespace/.
6. 浅谈current宏[EB/OL]. []. https://www.cnblogs.com/crybaby/p/14082593.html.
7. Linux源码[EB/OL]. []. https://elixir.bootlin.com/linux/v4.16.3/source.
8. list_entry详解[EB/OL]. []. linux源代码中的容器:list_entry_51CTO博客_linux 源代码.
手机扫一扫
移动阅读更方便
你可能感兴趣的文章