操作系统实验——系统调用:获取当前进程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 运维的环境中,我们经常会遇到维护同一台服务器上的多个程序,涉及到程序的启动.关闭和重启操作. 通常这些程序之间存在着相互依存的关系需要进行依次的启动关闭操作. 下面介绍几 ...
随机推荐
- 2020-10-14:Redisson分布式锁超时自动释放,会有什么问题?
福哥答案2020-10-14:#福大大架构师每日一题# [知乎:](https://www.zhihu.com/question/425541402) 如果线程1的锁被自动释放了,临界区的逻辑还没执行 ...
- 2022-03-30:有m个同样的苹果,认为苹果之间无差别, 有n个同样的盘子,认为盘子之间也无差别, 还有,比如5个苹果如果放进3个盘子, 那么1、3、1和1、1、3和3、1、1的放置方法,也认为是
2022-03-30:有m个同样的苹果,认为苹果之间无差别, 有n个同样的盘子,认为盘子之间也无差别, 还有,比如5个苹果如果放进3个盘子, 那么1.3.1和1.1.3和3.1.1的放置方法,也认为是 ...
- mysql基础_视图
介绍 MySQL 视图(View)是一种虚拟存在的表,同真实表一样,视图也由列和行构成,但视图并不实际存在于数据库中.行和列的数据来自于定义视图的查询中所使用的表,并且还是在使用视图时动态生成的. 优 ...
- Python asyncio之协程学习总结
实践环境 Python 3.6.2 什么是协程 协程(Coroutine)一种电脑程序组件,该程序组件通过允许暂停和恢复任务,为非抢占式多任务生成子程序.协程也可以简单理解为协作的程序,通过协同多任务 ...
- 如何使用 Megatron-LM 训练语言模型
在 PyTorch 中训练大语言模型不仅仅是写一个训练循环这么简单.我们通常需要将模型分布在多个设备上,并使用许多优化技术以实现稳定高效的训练.Hugging Face Accelerate 的创建 ...
- Python-Loguru:让记录日志更装13
" 今天勇哥来介绍一款让日志记录在 Python 中变得更加轻松愉快的库--Loguru.它提供了强大的功能和简洁的接口,使我们能够以更加灵活和直观的方式记录和管理日志信息,据说比loggi ...
- 推送服务接入指导(HarmonyOS篇)
消息推送作为App运营日常使用的用户促活和召回手段,是与用户建立持续互动和连接的良好方式.推送服务(Push Kit)是华为提供的消息推送平台,建立了从云端到终端的消息推送通道,本文旨在介绍Harmo ...
- zabbix监控服务器php
1 修改php配置文件 /apollo/env/php/thirdparty.php-7.3/etc/php-fpm.conf,添加pm.status pm.status_path = /phpfpm ...
- 自然语言处理 Paddle NLP - 开放域对话系统-理论
常见的对话系统 个人助手 •Apple Siri, Amazon Alexa, Baidu Xiaodu 客户服务•餐厅预定.商品咨询.债务催收 休闲娱乐 •Microsoft XiaoIce,Rep ...
- 一个跨平台的`ChatGPT`悬浮窗工具
一个跨平台的ChatGPT悬浮窗工具 使用avalonia实现的ChatGPT的工具,设计成悬浮窗,并且支持插件. 如何实现悬浮窗? 在使用avalonia实现悬浮窗也是非常的简单的. 实现我们需要将 ...