top/ps显示进程的[ xxx ]问题

结论

节省大家时间,抛出结论:

  • [ ]括起来的进程属于内核进程,无cmdline
  • 无[ ] 为用户进程,有cmdline

缘起

在我们用ps/top查看进程的时候在COMMAND一列,会发现有些进程被[ ]括起来或者kwork/0:,而有些没有。
具体如下:
在这里插入图片描述在这里插入图片描述

直接原因

man top查看下说明
在这里插入图片描述
man ps 查看一下
在这里插入图片描述意思就是:因为没有command line所以才会用[ ]括起来
以进程1和2为例
在这里插入图片描述直接看就是cmdline这个文件没有内容

root@tty-Ubuntu:/proc# cat 1/cmdline 
/sbin/initsplashroot@tty-Ubuntu:/proc# cat 2/c
cgroup           clear_refs       cmdline          comm             coredump_filter  cpuset           cwd/             
root@tty-Ubuntu:/proc# cat 2/cmdline 
root@tty-Ubuntu:/proc# 

打印深入追究

利用busybox的源码进行分析
在这里插入图片描述在这里插入图片描述

  1. 遍历了所有进程,并构建描述结构体
  2. 在display_process_list中遍历描述结构体,并依序打印
  3. 通过read_cmdline,获取并打印进程名
void FAST_FUNC read_cmdline(char *buf, int col, unsigned pid, const char *comm)
{
	int sz;
	char filename[sizeof("/proc/%u/cmdline") + sizeof(int)*3];

	sprintf(filename, "/proc/%u/cmdline", pid);
	sz = open_read_close(filename, buf, col - 1);
	if (sz > 0) {
		const char *base;
		int comm_len;

		buf[sz] = '\0';
		while (--sz >= 0 && buf[sz] == '\0')
			continue;
		/* Prevent basename("process foo/bar") = "bar" */
		strchrnul(buf, ' ')[0] = '\0';
		base = bb_basename(buf); /* before we replace argv0's NUL with space */
		while (sz >= 0) {
			if ((unsigned char)(buf[sz]) < ' ')
				buf[sz] = ' ';
			sz--;
		}
		if (base[0] == '-') /* "-sh" (login shell)? */
			base++;

		/* If comm differs from argv0, prepend "{comm} ".
		 * It allows to see thread names set by prctl(PR_SET_NAME).
		 */
		if (!comm)
			return;
		comm_len = strlen(comm);
		/* Why compare up to comm_len, not COMM_LEN-1?
		 * Well, some processes rewrite argv, and use _spaces_ there
		 * while rewriting. (KDE is observed to do it).
		 * I prefer to still treat argv0 "process foo bar"
		 * as 'equal' to comm "process".
		 */
		if (strncmp(base, comm, comm_len) != 0) {
			comm_len += 3;
			if (col > comm_len)
				memmove(buf + comm_len, buf, col - comm_len);
			snprintf(buf, col, "{%s}", comm);
			if (col <= comm_len)
				return;
			buf[comm_len - 1] = ' ';
			buf[col - 1] = '\0';
		}
	} else {
		snprintf(buf, col, "[%s]", comm ? comm : "?");
	}
}
  1. 通过/proc/%u/cmdline获取进程名
  2. 如果/proc/%u/cmdline为空,则使用comm加 [ ]
  3. 如果cmdline的base和comm不同,则打印comm加{ }

进程跟cmdline的关系

在linux中,进程分为用户空间进程内核空间进程

用户空间创建进程使用fork、exec

  • fork时只是创建新的task_struct,父子进程共用一份mm_struct
  • exec的时候,才会独立出mm_struct
  1. 在execve执行新程序时,会初始化mm_struct
  2. 把execve中传递的argv和envp保存到arg_start和env_start指定的地址中
  3. 在cat /proc//cmdline时则从arg_start的虚拟地址获取数据
    因此,只要是用户空间创建的进程经过execve的系统调用,都会有/proc//cmdline,

内核空间创建进程使用kthread_run

  1. 唤醒进程kthread_task来创建新进程
  2. 设置进程的属性,其中属性包括comm,但不包括cmdline

因此:

  • 用户进程有cmdline参数,会被打印出了,无[ ]
  • 内核进程无cmdline,会打印comm,有[ ]

转载自:https://blog.csdn.net/weixin_30778805/article/details/101788320?utm_medium=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromMachineLearnPai2-1.nonecase&depth_1-utm_source=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromMachineLearnPai2-1.nonecase

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值