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

本文解析了Linux中用户进程与内核进程的区别,重点介绍了cmdline文件的作用及其实现原理。用户进程经execve系统调用后,会有/proc//cmdline记录;内核进程由kthread_run创建,无cmdline,显示为[]括起来的进程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

结论

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

  • [ ]括起来的进程属于内核进程,无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

<think>好的,用户想知道如何让ps -ef命令的输出分页显示或者一部分一部分显示。首先,我需要回忆一下Linux命令中处理输出的常用方法。通常,当命令的输出过长时,可以使用管道符将结果传给分页工具,比如more或者less。 ps -ef本身会一次性列出所有进程,如果进程很多,终端可能会快速滚动,用户无法逐页查看。这时候,用more命令可以分页显示,按空格键翻页,回车键下一行。例如ps -ef | more。不过more的功能相对简单,只能向前翻页,不能回看。 相比之下,less命令更灵活,允许前后翻页,还支持搜索等功能。所以用户可能更适合使用ps -ef | less,这样查看起来更方便。 另外,如果用户想限制输出的行数,可以结合head或tail命令。比如ps -ef | head -n 20显示前20行,或者ps -ef | tail -n 20显示最后20行。不过这只能显示固定行数,不是真正的分页。 还有可能需要考虑ps命令本身是否有参数可以限制输出,但根据引用内容,ps主要是用来列出进程快照,没有内置的分页参数,所以必须依赖管道和其他工具。 另外,用户提到“一部分一部分显示”,可能是指动态更新,类似top命令。但ps是静态的,这时候可能需要使用watch命令,比如watch -n 1 'ps -ef | head',每秒刷新一次,但这和分页显示有所不同。 最后,需要确保命令的正确性,并提醒用户相关的快捷键,比如在less中按q退出,/搜索等。可能还需要提到如果输出内容特别多,如何组合使用grep来过滤结果,再分页显示,例如ps -ef | grep 'nginx' | less,这样更精准。 总结下来,主要解决方案是通过管道将ps -ef的输出传递给more或less,或者使用head/tail限制行数,或者用watch动态刷新。根据用户的具体需求,推荐最合适的方法。</think>要让`ps -ef`命令的输出分页或分段显示,可通过以下方法实现: --- ### 方法一:使用管道符结合`more`或`less`命令 1. **分页显示**(支持上下翻页): ```bash ps -ef | less ``` - 按`空格键`向下翻页,按`B`键向上翻页,按`Q`键退出[^2][^4]。 - 支持搜索功能:输入`/关键词`后按回车,例如`/nginx`查找包含"nginx"的进程。 2. **逐行显示**(按需加载): ```bash ps -ef | more ``` - 按`回车键`逐行显示,按`空格键`翻页,按`Q`键退出[^2][^4]。 --- ### 方法二:结合`head`或`tail`限制显示行数 1. **显示前N行**: ```bash ps -ef | head -n 20 # 仅显示前20行 ``` 2. **显示后N行**: ```bash ps -ef | tail -n 20 # 仅显示最后20行 ``` --- ### 方法三:动态刷新显示(类似`top`) 若需持续监控进程变化,可使用`watch`命令: ```bash watch -n 1 'ps -ef | head -n 20' # 每秒刷新一次,显示前20行 ``` - 按`Ctrl+C`终止监控[^2]。 --- ### 进阶用法:过滤后分页 结合`grep`过滤特定进程再分页: ```bash ps -ef | grep "nginx" | less # 仅显示包含"nginx"的进程并分页 ``` --- ### 总结 | 场景 | 推荐命令 | |----------------------|------------------------------| | 完整分页浏览 | `ps -ef | less` | | 简单分页 | `ps -ef | more` | | 动态刷新 | `watch -n 1 'ps -ef'` | | 精准过滤后分页 | `ps -ef | grep "xxx" | less` | ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值