Linux内核PID管理

Linux内核PID管理

前言

了解Linux内核PID管理的目的是想了解:当kill掉一个进程之后,/proc/目录下对应的pid目录是否会立即消失。

proc/pid

proc是一个虚拟文件系统,文件系统在注册时都会注册属于该文件系统的文件操作函数(file operations)和节点操作函数(inode operations),而proc文件系统的根目录作为一个特殊的文件节点,在文件系统注册时,还为该节点注册了特定的file operations和inode operations,进程对应的pid目录便是通过该节点的file operations来创建的:

/*
 * This is the root "inode" in the /proc tree..
 */
struct proc_dir_entry proc_root = {
   
	.low_ino	= PROC_ROOT_INO,
	.namelen	= 5,
	.mode		= S_IFDIR | S_IRUGO | S_IXUGO,
	.nlink		= 2,
	.refcnt		= REFCOUNT_INIT(1),
	.proc_iops	= &proc_root_inode_operations,
	.proc_fops	= &proc_root_operations,
	.parent		= &proc_root,
	.subdir		= RB_ROOT,
	.name		= "/proc",
};

/*
 * The root /proc directory is special, as it has the
 * <pid> directories. Thus we don't use the generic
 * directory handling functions for that..
 */
static const struct file_operations proc_root_operations = {
   
	.read		 = generic_read_dir,
	.iterate_shared	 = proc_root_readdir,
	.llseek		= generic_file_llseek,
};

static int proc_fill_super(struct super_block *s, struct fs_context *fc)
{
   
	......
	pde_get(&proc_root);
	root_inode = proc_get_inode(s, &proc_root);
	if (!root_inode) {
   
		pr_err("proc_fill_super: get root inode failed\n");
		return -ENOMEM;
	}

	s->s_root = d_make_root(root_inode);
	if (!s->s_root) {
   
		pr_err("proc_fill_super: allocate dentry failed\n");
		return -ENOMEM;
	}
	......
}

当对proc文件系统的根目录进行访问时,如ls命令显示/proc目录下的文件时,其调用栈如下(即通过系统调用getdents来获取/proc下所有但的目录项,每一个目录项对应于一个文件):

__arm64_sys_getdents64
	ksys_getdents64
		iterate_dir
			proc_root_readdir

在/proc目录下的文件分为两种:通过proc_create等接口创建产生的文件,如cpuinfo;pid目录文件。

static int proc_root_readdir(struct file *file, struct dir_context *ctx)
{
   
	if (ctx->pos < FIRST_PROCESS_ENTRY) {
   
		int error = proc_readdir(file, ctx); //先读取普通的文件目录,如通过proc_create创建的cpuinfo等节点
		if (unlikely(error <= 0))
			return error;
		ctx->pos = FIRST_PROCESS_ENTRY;
	}

	return proc_pid_readdir(file, ctx);//读取pid目录节点
}

通过proc_pid_readdir函数读取pid目录文件的过程为:通过next_tgid遍历系统中的进程;遍历的过程中调用proc_fill_cache将进程信息以目录项(dentry)的形式填入用户缓冲区。也就是说每一次读取/proc目录,都会执行proc_pid_readdir函数根据当前系统中的进程构建pid目录项,所以当/proc下没有某一个pid目录时,表示该pid对应的进程一定不在。

/* for the /proc/ directory itself, after non-process stuff has been done */
int proc_pid_readdir(struct file *file, struct dir_context *ctx)
{
   
	struct tgid_iter iter;
	struct pid_namespace *ns = proc_pid_ns(file_inode(file));
	loff_t pos = ctx->pos;

	if (pos >= PID_MAX_LIMIT + TGID_OFFSET)
		return 0;

	if (pos == TGID_OFFSET - 2) {
   
		struct inode *inode = d_inode(ns->proc_self);
		if (!dir_emit(ctx, "self", 4, inode->i_ino, DT_LNK))
			return 0;
		ctx->pos = pos = pos + 1;
	}
	if (pos == TGID_OFFSET - 1) {
   
		struct inode *inode = d_inode(ns->proc_thread_self);
		if (!dir_emit(ctx, "thread-self", 11, inode->i_ino, DT_LNK))
  • 4
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值