実現したいこと
Linux初学者です。プログラムをsudo権限でバックグラウンド実行した時に表示されるPIDと、プログラム内でgetpid()
するPIDと一致させたいです。
上記「プログラム」は下記をコンパイルしたものです。
C
1//cpu_hog.c 2 3#include <stdio.h> 4#include <unistd.h> 5 6int main(void) 7{ 8 printf("PID: <%d>\n", getpid()); 9 fflush(stdout); 10 return 0; 11}
補足:事象が再現する最小限のコードを貼り付けています。元々やろうとしていた事(この疑問を持ったきっかけ)については備考欄に記載しています。
発生している問題・分からないこと
shell
1$ gcc -O0 cpu_hog.c 2$ taskset -c 0 nice -n 19 ./a.out & sudo taskset -c 0 nice -n -10 ./a.out & 3[7] 66596 4[8] 66597 5$ 6PID: <66596> 7PID: <66600> 8 9[7] Done taskset -c 0 nice -n 19 ./a.out 10[8] Done sudo taskset -c 0 nice -n -10 ./a.out 11$
sudo
で実行しない場合、[7] 66596
, PID: <66596>
のように2つのPIDが一致しています。
しかしsudo
で実行した方のプロセスは[8] 66597
, PID: <66600>
のように異なるPIDが表示されています。これについて何点か質問したいです。
質問①そもそも上記の事象が起こる原因
melian様からのコメントで解決済み
基本的なことは勉強した結果、下記のように考えました。あっているでしょうか?
taskset
およびnice
は、内部でclone,forkせずにexec
しているためPIDが同じになるsudo
は内部でforkcloneしてからexec
しているのでPIDが異なる
質問② PIDを一致させる方法
上記のshell出力において、[8] 66597
はsudo
のpid、PID: <66600>
はa.out
のpidという認識です。これを一致させるにはどうしたらいいでしょうか?(質問タイトルには両方sudoのPIDにしたいと書いていますが、一致すればどちらでもいいです)
試したこと・調べたこと
- teratailやGoogle等で検索した
- ソースコードを自分なりに変更した
- 知人に聞いた
- その他
上記の詳細・結果
一旦sudo無しの方は無視して、sudoありの方だけPIDを一致させようと考えました。
a.out
の親プロセスのpidを見ればsudo
のpidがわかるかと思い、cpu_hog.c
のgetpid
をgetppid
に変更してみました。その結果がこれです。
$ taskset -c 0 nice -n 19 ./a.out & sudo taskset -c 0 nice -n -10 ./a.out & [10] 75810 [11] 75811 PID: <1799> PID: <75813> $ [10] Done taskset -c 0 nice -n 19 ./a.out [11] Done sudo taskset -c 0 nice -n -10 ./a.out
[10]
(sudo無し)の方については、bashのPID1799
が出力されており、想定通りの動きです。
しかし[11]
(sudoあり)の方は余計にわからなくなってしまいました。[11] 75811
とPID: <75813>
という異なるPIDが表示されていますが、これはそれぞれ何のPIDなのでしょうか。
補足①バージョン情報
shell
1$ lsb_release -a 2No LSB modules are available. 3Distributor ID: Ubuntu 4Description: Ubuntu 24.04.2 LTS 5Release: 24.04 6Codename: noble 7 8$ gcc --version 9gcc (Ubuntu 13.3.0-6ubuntu2~24.04) 13.3.0 10Copyright (C) 2023 Free Software Foundation, Inc. 11This is free software; see the source for copying conditions. There is NO 12warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 13 14$ dpkg -l | grep libc6 15ii libc6:amd64 2.39-0ubuntu8.4 amd64 GNU C Library: Shared libraries 16ii libc6-dbg:amd64 2.39-0ubuntu8.4 amd64 GNU C Library: detached debugging symbols 17ii libc6-dev:amd64 2.39-0ubuntu8.4 amd64 GNU C Library: Development Libraries and Header Files
補足②
教えていただいた内容を盛り込んで更新しました
元々はプロセスの優先順位と実行時間の関係を観察しようとしていました。質問内容には直接関係ありませんが、一応元のコードも貼り付けておきます。
C
1#include <stdio.h> 2#include <unistd.h> 3#include <time.h> 4#include <sys/time.h> 5#include <libproc2/pids.h> 6#include <string.h> 7 8int main(void) 9{ 10 struct pids_info *info = NULL; 11 enum pids_item item[] = {PIDS_ID_PPID, PIDS_CMD}; 12 procps_pids_new(&info, item, 2); // 第3引数はitem[]の要素数 13 14 pid_t ppid = getppid(); 15 struct pids_fetch *pidread = procps_pids_select(info, (unsigned int *)&ppid, 1, PIDS_SELECT_PID); 16 17 pid_t pppid = pidread->stacks[0]->head[0].result.u_int; 18 char *pppcmd = pidread->stacks[0]->head[1].result.str; 19 20 clock_t start = clock(); 21 22 // 実時間の開始(リアルタイム時計) 23 struct timeval real_start, real_end; 24 gettimeofday(&real_start, NULL); 25 26 volatile unsigned long long count = 0; 27 for (unsigned long long i = 0; i < 5000000000ULL; i++) 28 { 29 count += i; 30 } 31 32 clock_t end = clock(); 33 34 // 実時間の終了 35 gettimeofday(&real_end, NULL); 36 37 double elapsed = (double)(end - start) / CLOCKS_PER_SEC; 38 39 double real_time = (real_end.tv_sec - real_start.tv_sec) + (real_end.tv_usec - real_start.tv_usec) / 1000000.0; 40 41 pid_t disp = (strcmp(pppcmd, "sudo") == 0) ? pppid : getpid(); 42 printf("\n<%d>Done. CPU time: %.2f seconds Real time: %.2f sec", disp, elapsed, real_time); 43 fflush(stdout); 44 return 0; 45}
追記 double cloneの詳細
ご参考までに、手元でdouble cloneが発生したソースコードとコンソール出力を貼り付けておきます。環境については「補足①バージョン情報」に掲載しています。
C
1//check_pid.c 2#include <stdio.h> 3#include <unistd.h> 4#include <stdlib.h> 5#include <libproc2/pids.h> 6#include <string.h> 7 8int main(void) 9{ 10 struct pids_info *info = NULL; 11 enum pids_item item[] = {PIDS_ID_PPID, PIDS_CMD}; 12 procps_pids_new(&info, item, 2); 13 14 pid_t ppid = getppid(); 15 struct pids_fetch *pidread = NULL; 16 pidread = procps_pids_select(info, (unsigned int *)&ppid, 1, PIDS_SELECT_PID); 17 printf("PID: <%d>\n", getpid()); 18 printf("PPID: <%d>\n", getppid()); 19 printf("PPPID: <%d>\n", pidread->stacks[0]->head[0].result.u_int); 20 printf("PPPCMD: <%s>\n", pidread->stacks[0]->head[1].result.str); 21 fflush(stdout); 22 system("ps afT"); 23 fflush(stdout); 24 25 return 0; 26}
shell
1$ gcc -O0 -Wall -Wextra check_pid.c -lproc2 2$ sudo ./a.out & 3[1] 3952 4$ 5PID: <3955> 6PPID: <3954> 7PPPID: <3952> 8PPPCMD: <sudo> 9 PID TTY STAT TIME COMMAND 10 1715 pts/3 Ss+ 0:00 /bin/bash --init-file /home/user/.vscode-server/cli/servers/Stable-xxxxxxxxxxxxxxxxxxxxxxxx 11 3952 pts/3 S 0:00 \_ sudo ./a.out 12 3954 pts/4 Ss+ 0:00 \_ sudo ./a.out 13 3955 pts/4 S 0:00 \_ ./a.out 14 3956 pts/4 S 0:00 \_ sh -c -- ps afT 15 3957 pts/4 R 0:00 \_ ps afT 16 974 tty1 Ss+ 0:00 /sbin/agetty -o -p -- \u --noclear - linux 17 18[1]+ Done sudo ./a.out 19$

回答2件
あなたの回答
tips
プレビュー