操作系统实验——系统调用:获取当前进程pid和ppid
目录
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的更多相关文章
- linux获取精准进程PID之pgrep命令
pgrep 是通过程序的名字来查询进程的工具,一般是用来判断程序是否正在运行.在服务器的配置和管理中,这个工具常被应用,简单明了. 用法: #pgrep [选项] [程序名] pgrep [-flvx ...
- windows 下获取父进程pid
DWORD GetParentProcessID(DWORD dwProcessId) { LONG status; DWORD dwParentPID = (DWORD)-1; HANDLE hPr ...
- 进程PID 与PPID
# 同一个程序执行多次是多个进程 import time import os print('爹是:',os.getppid()) #查看父进程 print('me是: ',os.getpid()) # ...
- 操作系统实验一:进程管理(含成功运行C语言源代码)
目录 操作系统实验一:进程管理 1.实验目的 2.实验内容 3.实验准备 3.1.1进程的含义 3.1.2进程的状态 3.1.3进程状态之间的转换 3.2 进程控制块PCB 3.2.1进程控制块的作用 ...
- Bash Shell 获取进程 PID
转载地址:http://weyo.me/pages/techs/linux-get-pid/ 导读 Linux 的交互式 Shell 与 Shell 脚本存在一定的差异,主要是由于后者存在一个独立的运 ...
- linux: 获取监听指定端口的进程PID
在 linux 下经常需要杀死(重启)监听某端口的进程, 因此就写了一个小脚本, 通过 ss 命令获取监听制定端口的进程 PID, 然后通过 kill 命令结束掉进程: #!/bin/sh # set ...
- delphi根据进程PID获取程序所在路径的函数(用OpenProcess取得句柄,用GetModuleFileNameEx取得程序名)
uses psapi; {根据进程PID获取程序所在路径的函数}function GetProcessExePath(PID: Cardinal): string;varpHandle: THandl ...
- 扫描系统进程和获取某进程的PID
扫描系统的所有进程 #include <stdio.h> #include <windows.h> #include <tlhelp32.h> int scan() ...
- linux命令(26):Bash Shell 获取进程 PID
转载地址:http://weyo.me/pages/techs/linux-get-pid/ 根据pid,kill该进程:http://www.cnblogs.com/lovychen/p/54113 ...
- Python 使用标准库根据进程名获取进程PID
应用场景 在进行 Linux 运维的环境中,我们经常会遇到维护同一台服务器上的多个程序,涉及到程序的启动.关闭和重启操作. 通常这些程序之间存在着相互依存的关系需要进行依次的启动关闭操作. 下面介绍几 ...
随机推荐
- 2022-09-14:以下go语言代码输出什么?A:0 0;B:0 1;C:1 1;D:1 0。 package main func main() { println(f(1)) } func
2022-09-14:以下go语言代码输出什么?A:0 0:B:0 1:C:1 1:D:1 0. package main func main() { println(f(1)) } func f(x ...
- 2022-09-12:以下go语言代码输出什么?A:true;B:false;C:无法编译;D:运行时 panic。 package main func main() { var x chan<-
2022-09-12:以下go语言代码输出什么?A:true:B:false:C:无法编译:D:运行时 panic. package main func main() { var x chan< ...
- 2021-03-30:给定一个整数组成的无序数组arr,值可能正、可能负、可能0。给定一个整数值K,找到arr的所有子数组里,哪个子数组的累加和<=K,并且是长度最大的。返回其长度。
2021-03-30:给定一个整数组成的无序数组arr,值可能正.可能负.可能0.给定一个整数值K,找到arr的所有子数组里,哪个子数组的累加和<=K,并且是长度最大的.返回其长度. 福大大 答 ...
- SQL Server2019 删除列字段
命令: 有默认值时用:alter table 表名 DROP 约束 alter table 表名 DROP COLUMN 列名 例如: alter table LJEL005H DROP COLUM ...
- 代码随想录算法训练营Day50 动态规划
代码随想录算法训练营 代码随想录算法训练营Day50 动态规划| 123.买卖股票的最佳时机III 188.买卖股票的最佳时机IV 123.买卖股票的最佳时机III 题目链接:123.买卖股票的最佳时 ...
- 【Photoshop】切图保存小坑(选择png格式得到gif问题)
默认情况下:Photoshop 导出切片为[GIF]格式 当你很嗨皮的把[GIF]调整为[PNG]或[JPG]格式,并保存时: 你会发现,自己的图片格式莫名其妙还是[GIF]: 但,我们的期望是: 原 ...
- Kubernetes(k8s)包管理工具Helm:Helm包管理
目录 一.系统环境 二.前言 三.包管理工具Helm简介 四.安装部署helm 五.配置helm以及helm常用命令 六.使用helm安装应用 七.搭建helm私有仓库 八.总结 一.系统环境 本文主 ...
- CKS 考试题整理 (05)-Container 安全上下文
Context Container Security Context 应在特定 namespace 中修改 Deployment. Task 按照如下要求修改 sec-ns 命名空间里的 Deploy ...
- Jconsole 开启远程连接遇到的一些坑
最近在学习 JVM,其中涉及到性能.内存等指标分析需要使用工具分享,Java 提供了几个可视化工具来监控和管理 Java 应用,比如 Jconsole.JVisual.JMC,他们以图形化的界面实时的 ...
- .NET周报 【6月第4期 2023-06-25】
国内文章 如何在long-running task中调用async方法 https://www.cnblogs.com/eventhorizon/p/17497359.html long-runnin ...