目录

一.题目介绍

二.实验思路

三.核心代码

四。遇到的问题及一些解决方法

五.参考文献

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 源代码.

操作系统实验——系统调用:获取当前进程pid和ppid的更多相关文章

  1. linux获取精准进程PID之pgrep命令

    pgrep 是通过程序的名字来查询进程的工具,一般是用来判断程序是否正在运行.在服务器的配置和管理中,这个工具常被应用,简单明了. 用法: #pgrep [选项] [程序名] pgrep [-flvx ...

  2. windows 下获取父进程pid

    DWORD GetParentProcessID(DWORD dwProcessId) { LONG status; DWORD dwParentPID = (DWORD)-1; HANDLE hPr ...

  3. 进程PID 与PPID

    # 同一个程序执行多次是多个进程 import time import os print('爹是:',os.getppid()) #查看父进程 print('me是: ',os.getpid()) # ...

  4. 操作系统实验一:进程管理(含成功运行C语言源代码)

    目录 操作系统实验一:进程管理 1.实验目的 2.实验内容 3.实验准备 3.1.1进程的含义 3.1.2进程的状态 3.1.3进程状态之间的转换 3.2 进程控制块PCB 3.2.1进程控制块的作用 ...

  5. Bash Shell 获取进程 PID

    转载地址:http://weyo.me/pages/techs/linux-get-pid/ 导读 Linux 的交互式 Shell 与 Shell 脚本存在一定的差异,主要是由于后者存在一个独立的运 ...

  6. linux: 获取监听指定端口的进程PID

    在 linux 下经常需要杀死(重启)监听某端口的进程, 因此就写了一个小脚本, 通过 ss 命令获取监听制定端口的进程 PID, 然后通过 kill 命令结束掉进程: #!/bin/sh # set ...

  7. delphi根据进程PID获取程序所在路径的函数(用OpenProcess取得句柄,用GetModuleFileNameEx取得程序名)

    uses psapi; {根据进程PID获取程序所在路径的函数}function GetProcessExePath(PID: Cardinal): string;varpHandle: THandl ...

  8. 扫描系统进程和获取某进程的PID

    扫描系统的所有进程 #include <stdio.h> #include <windows.h> #include <tlhelp32.h> int scan() ...

  9. linux命令(26):Bash Shell 获取进程 PID

    转载地址:http://weyo.me/pages/techs/linux-get-pid/ 根据pid,kill该进程:http://www.cnblogs.com/lovychen/p/54113 ...

  10. Python 使用标准库根据进程名获取进程PID

    应用场景 在进行 Linux 运维的环境中,我们经常会遇到维护同一台服务器上的多个程序,涉及到程序的启动.关闭和重启操作. 通常这些程序之间存在着相互依存的关系需要进行依次的启动关闭操作. 下面介绍几 ...

随机推荐

  1. 2022-11-30:小红拿到了一个仅由r、e、d组成的字符串 她定义一个字符e为“好e“ : 当且仅当这个e字符和r、d相邻 例如“reeder“只有一个“好e“,前两个e都不是“好e“,只有第三个

    2022-11-30:小红拿到了一个仅由r.e.d组成的字符串 她定义一个字符e为"好e" : 当且仅当这个e字符和r.d相邻 例如"reeder"只有一个&q ...

  2. 2020-11-19:go中,defer原理是什么?

    福哥答案2020-11-19:- - 什么是defer - defer是go语言提供的一种用于注册延迟调用的机制:让函数或者语句在当前函数执行完毕(包括return正常结束或者panic导致的异常结束 ...

  3. 2022-01-31:迷宫 III。 由空地和墙组成的迷宫中有一个球。球可以向上(u)下(d)左(l)右(r)四个方向滚动,但在遇到墙壁前不会停止滚动。当球停下时,可以选择下一个方向。迷宫中还有一个洞

    2022-01-31:迷宫 III. 由空地和墙组成的迷宫中有一个球.球可以向上(u)下(d)左(l)右(r)四个方向滚动,但在遇到墙壁前不会停止滚动.当球停下时,可以选择下一个方向.迷宫中还有一个洞 ...

  4. < Python全景系列-6 > 掌握Python面向对象编程的关键:深度探索类与对象

    欢迎来到我们的系列博客<Python全景系列>!在这个系列中,我们将带领你从Python的基础知识开始,一步步深入到高级话题,帮助你掌握这门强大而灵活的编程语法.无论你是编程新手,还是有一 ...

  5. Must use destructuring props assignmenteslint

    eslint 检测提示Must use destructuring props assignmenteslint 使用对象结构就可以解决了

  6. 代码随想录算法训练营Day8字符串|●  344.反转字符串  541. 反转字符串II  剑指Offer 05.替换空格  151.翻转字符串里的单词  剑指Offer58-II.左旋转字符串

    344.反转字符串 题目连接:344.反转字符串 编写一个函数,其作用是将输入的字符串反转过来.输入字符串以字符数组 s 的形式给出. 不要给另外的数组分配额外的空间,__你必须原地修改输入数组.使用 ...

  7. chrome 应用程序无法启动,因为应用程序的并行配置不正确

    win10系统谷歌浏览器无法启动,系统报错,如下图: 解决方案: 步骤1:进入chrome的安装路径C:\Program Files (x86)\Google\Chrome\... ...(找到自己的 ...

  8. 曲线艺术编程 coding curves 第八章 贝赛尔曲线(Bézier Curves)

    贝赛尔曲线(Bézier Curves) 原作:Keith Peters https://www.bit-101.com/blog/2022/11/coding-curves/ 译者:池中物王二狗(s ...

  9. PicoRV32-on-PYNQ-Z2: An FPGA-based SoC System——RISC-V On PYNQ项目复现

    本文参考: 1️⃣ 原始工程 2️⃣ 原始工程复现教程 3️⃣ RISCV工具链安装教程 本文工程: https://bhpan.buaa.edu.cn:443/link/4B08916BF2CDB4 ...

  10. 一种实现Spring动态数据源切换的方法

    1 目标 不在现有查询代码逻辑上做任何改动,实现dao维度的数据源切换(即表维度) 2 使用场景 节约bdp的集群资源.接入新的宽表时,通常uat验证后就会停止集群释放资源,在对应的查询服务器uat环 ...