Linux-如何在C中更改分叉进程的信息
标题听起来可能有点奇怪,因为Linux-如何在C中更改分叉进程的信息,c,linux,gcc,fork,C,Linux,Gcc,Fork,标题听起来可能有点奇怪,因为ps aux我看到: root 20953 0.0 0.0 9528 1280 ? Ss Apr28 0:07 sendmail: accepting connections 其中“接受连接”类似于sendmail流程的标题。它不是参数,因为cat/proc/20953/cmdline返回sendmail:accepting connections(空格而不是0x00): /proc fs中的参数用空字节分隔: # cat /
ps aux
我看到:
root 20953 0.0 0.0 9528 1280 ? Ss Apr28 0:07 sendmail: accepting connections
其中“接受连接”类似于sendmail流程的标题。它不是参数,因为cat/proc/20953/cmdline
返回sendmail:accepting connections
(空格而不是0x00):
/proc fs中的参数用空字节分隔:
# cat /proc/26511/cmdline |hexdump -C
00000000 2f 62 69 6e 2f 62 61 73 68 00 2f 77 65 62 72 6f |/bin/bash./webro|
00000010 6f 74 2f 70 72 6f 72 61 69 6c 2f 73 63 72 69 70 |ot/prorail/scrip|
00000020 74 73 2f 73 79 6e 63 6c 6f 6f 70 2e 73 68 00 |ts/syncloop.sh.|
0000002f
因此,当我在C中使用fork()时,如何设置此进程信息,以便识别哪个进程?sendmail有多种方法,具体取决于系统。请参阅源代码中sendmail/conf.C中的setproctitle:
#define SPT_NONE 0 /* don't use it at all */
#define SPT_REUSEARGV 1 /* cover argv with title information */
#define SPT_BUILTIN 2 /* use libc builtin */
#define SPT_PSTAT 3 /* use pstat(PSTAT_SETCMD, ...) */
#define SPT_PSSTRINGS 4 /* use PS_STRINGS->... */
#define SPT_SYSMIPS 5 /* use sysmips() supported by NEWS-OS 6 */
#define SPT_SCO 6 /* write kernel u. area */
#define SPT_CHANGEARGV 7 /* write our own strings into argv[] */
有关详细信息,请参阅conf.c中的setproctitle例程。我找到了答案,尽管问题不是同一个问题。所有学分都应该交给
#包括
#包括
int main(int argc,字符**argv)
{
strcpy(argv[0],“你好,世界!”);
睡眠(10);
返回0;
}
在本文中:作者解释了如何更改流程标题。我猜setproctitle是的,所以他尝试在linux上实现它。下面是来自
我还没有测试过。我还没有检查它是否使用库中的其他函数,因此代码可能不完整。请随意测试它并留下一个结果
/*
* Sets the process title to the specified title. Note that this may fail if
* the kernel doesn't support PR_SET_MM_MAP (kernels <3.18).
*/
int setproctitle(char *title)
{
static char *proctitle = NULL;
char buf[2048], *tmp;
FILE *f;
int i, len, ret = 0;
/* We don't really need to know all of this stuff, but unfortunately
* PR_SET_MM_MAP requires us to set it all at once, so we have to
* figure it out anyway.
*/
unsigned long start_data, end_data, start_brk, start_code, end_code,
start_stack, arg_start, arg_end, env_start, env_end,
brk_val;
struct prctl_mm_map prctl_map;
f = fopen_cloexec("/proc/self/stat", "r");
if (!f) {
return -1;
}
tmp = fgets(buf, sizeof(buf), f);
fclose(f);
if (!tmp) {
return -1;
}
/* Skip the first 25 fields, column 26-28 are start_code, end_code,
* and start_stack */
tmp = strchr(buf, ' ');
for (i = 0; i < 24; i++) {
if (!tmp)
return -1;
tmp = strchr(tmp+1, ' ');
}
if (!tmp)
return -1;
i = sscanf(tmp, "%lu %lu %lu", &start_code, &end_code, &start_stack);
if (i != 3)
return -1;
/* Skip the next 19 fields, column 45-51 are start_data to arg_end */
for (i = 0; i < 19; i++) {
if (!tmp)
return -1;
tmp = strchr(tmp+1, ' ');
}
if (!tmp)
return -1;
i = sscanf(tmp, "%lu %lu %lu %*u %*u %lu %lu",
&start_data,
&end_data,
&start_brk,
&env_start,
&env_end);
if (i != 5)
return -1;
/* Include the null byte here, because in the calculations below we
* want to have room for it. */
len = strlen(title) + 1;
proctitle = realloc(proctitle, len);
if (!proctitle)
return -1;
arg_start = (unsigned long) proctitle;
arg_end = arg_start + len;
brk_val = syscall(__NR_brk, 0);
prctl_map = (struct prctl_mm_map) {
.start_code = start_code,
.end_code = end_code,
.start_stack = start_stack,
.start_data = start_data,
.end_data = end_data,
.start_brk = start_brk,
.brk = brk_val,
.arg_start = arg_start,
.arg_end = arg_end,
.env_start = env_start,
.env_end = env_end,
.auxv = NULL,
.auxv_size = 0,
.exe_fd = -1,
};
ret = prctl(PR_SET_MM, PR_SET_MM_MAP, (long) &prctl_map, sizeof(prctl_map), 0);
if (ret == 0)
strcpy((char*)arg_start, title);
else
INFO("setting cmdline failed - %s", strerror(errno));
return ret;
}
/*
*将流程标题设置为指定的标题。请注意,如果
*内核不支持PR\u SET\u MM\u映射(内核可能与我的问题有点不同,尽管那里有我问题的答案。我问如何用C来做。答案被接受并不是我想要的答案。我将复制正确答案,并将关闭它的决定留给版主。感谢链接!这将覆盖其他内容。我找到了另一个答案解决方案-我将在单独的答案中发布
#include <string.h>
#include <unistd.h>
int main(int argc, char** argv)
{
strcpy(argv[0], "Hello, world!");
sleep(10);
return 0;
}
/*
* Sets the process title to the specified title. Note that this may fail if
* the kernel doesn't support PR_SET_MM_MAP (kernels <3.18).
*/
int setproctitle(char *title)
{
static char *proctitle = NULL;
char buf[2048], *tmp;
FILE *f;
int i, len, ret = 0;
/* We don't really need to know all of this stuff, but unfortunately
* PR_SET_MM_MAP requires us to set it all at once, so we have to
* figure it out anyway.
*/
unsigned long start_data, end_data, start_brk, start_code, end_code,
start_stack, arg_start, arg_end, env_start, env_end,
brk_val;
struct prctl_mm_map prctl_map;
f = fopen_cloexec("/proc/self/stat", "r");
if (!f) {
return -1;
}
tmp = fgets(buf, sizeof(buf), f);
fclose(f);
if (!tmp) {
return -1;
}
/* Skip the first 25 fields, column 26-28 are start_code, end_code,
* and start_stack */
tmp = strchr(buf, ' ');
for (i = 0; i < 24; i++) {
if (!tmp)
return -1;
tmp = strchr(tmp+1, ' ');
}
if (!tmp)
return -1;
i = sscanf(tmp, "%lu %lu %lu", &start_code, &end_code, &start_stack);
if (i != 3)
return -1;
/* Skip the next 19 fields, column 45-51 are start_data to arg_end */
for (i = 0; i < 19; i++) {
if (!tmp)
return -1;
tmp = strchr(tmp+1, ' ');
}
if (!tmp)
return -1;
i = sscanf(tmp, "%lu %lu %lu %*u %*u %lu %lu",
&start_data,
&end_data,
&start_brk,
&env_start,
&env_end);
if (i != 5)
return -1;
/* Include the null byte here, because in the calculations below we
* want to have room for it. */
len = strlen(title) + 1;
proctitle = realloc(proctitle, len);
if (!proctitle)
return -1;
arg_start = (unsigned long) proctitle;
arg_end = arg_start + len;
brk_val = syscall(__NR_brk, 0);
prctl_map = (struct prctl_mm_map) {
.start_code = start_code,
.end_code = end_code,
.start_stack = start_stack,
.start_data = start_data,
.end_data = end_data,
.start_brk = start_brk,
.brk = brk_val,
.arg_start = arg_start,
.arg_end = arg_end,
.env_start = env_start,
.env_end = env_end,
.auxv = NULL,
.auxv_size = 0,
.exe_fd = -1,
};
ret = prctl(PR_SET_MM, PR_SET_MM_MAP, (long) &prctl_map, sizeof(prctl_map), 0);
if (ret == 0)
strcpy((char*)arg_start, title);
else
INFO("setting cmdline failed - %s", strerror(errno));
return ret;
}