结论
节省大家时间,抛出结论:
- [ ]括起来的进程属于内核进程,无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的源码进行分析
- 遍历了所有进程,并构建描述结构体
- 在display_process_list中遍历描述结构体,并依序打印
- 通过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 : "?");
}
}
- 通过
/proc/%u/cmdline
获取进程名 - 如果
/proc/%u/cmdline
为空,则使用comm加 [ ] - 如果cmdline的base和comm不同,则打印comm加{ }
进程跟cmdline的关系
在linux中,进程分为用户空间进程和内核空间进程
用户空间创建进程使用fork、exec
- fork时只是创建新的task_struct,父子进程共用一份mm_struct
- exec的时候,才会独立出mm_struct
- 在execve执行新程序时,会初始化mm_struct
- 把execve中传递的argv和envp保存到arg_start和env_start指定的地址中
- 在cat /proc//cmdline时则从arg_start的虚拟地址获取数据
因此,只要是用户空间创建的进程经过execve的系统调用,都会有/proc//cmdline,
内核空间创建进程使用kthread_run
- 唤醒进程kthread_task来创建新进程
- 设置进程的属性,其中属性包括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