プロセスID - ToguchiYuto/linuxsystemprogram GitHub Wiki
- アイドルプロセスのIDは0になる。
- initプロセスのIDは1になる。
- Linuxが起動したあと以下のディレクトリ内の実行可能なファイルが実行される。実行可能なファイルが存在しない場合、カーネルパニックが発生する。
- /sbin/init
- /etc/init
- /bin/init
- /bin/sh
- pidはプロセスが生成されたあと自動的にわりあてられ、最大のpidは32768に設定されている。32768まで使い切ったら若い番号が再利用される。
[root@localhost ~]# cat /proc/sys/kernel/pid_max
32768
[root@localhost ~]#
- すべてのプロセスの親プロセスはinitになる。systemdの場合、以下のような階層構造になる。
[root@localhost ~]# pstree -p
systemd(1)─┬─NetworkManager(854)─┬─dhclient(1047)
│ ├─{NetworkManager}(862)
│ └─{NetworkManager}(866)
├─agetty(1394)
├─auditd(798)───{auditd}(799)
├─chronyd(836)
├─crond(1385)
├─dbus-daemon(827)───{dbus-daemon}(842)
├─firewalld(853)───{firewalld}(1044)
├─lvmetad(519)
├─master(1589)─┬─pickup(1591)
│ └─qmgr(1592)
├─polkitd(826)─┬─{polkitd}(839)
│ ├─{polkitd}(845)
│ ├─{polkitd}(846)
│ ├─{polkitd}(848)
│ ├─{polkitd}(849)
│ └─{polkitd}(850)
├─rsyslogd(1289)─┬─{rsyslogd}(1296)
│ └─{rsyslogd}(1297)
├─sshd(1290)─┬─sshd(1601)───sshd(1607)─┬─bash(1609)───sudo(1737)───bash(1759)───pstree(4269)
│ │ └─bash(1617)───sleep(4268)
│ └─sshd(1605)───sshd(1639)───sftp-server(1672)
├─systemd-journal(502)
├─systemd-logind(821)
├─systemd-udevd(531)
└─tuned(1293)─┬─{tuned}(1580)
├─{tuned}(1581)
├─{tuned}(1587)
└─{tuned}(1590)
[root@localhost ~]#
以下のプログラムを実行すると、プログラムの親プロセスのPIDと自身のPIDを取得することができる。
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
void main(){
printf("Parent PID %d\n", getppid());
printf("PID %d\n", getpid());
sleep(1000);
}
[debug@localhost linux_system_program]$ ./a.out
Parent PID 8419
PID 8519
[root@localhost ~]# pstree -p
systemd(1)─┬─NetworkManager(854)─┬─dhclient(1047)
│ ├─{NetworkManager}(862)
│ └─{NetworkManager}(866)
...
├─sshd(1290)─┬─sshd(8252)───sshd(8258)───bash(8259)───sudo(9005)───bash(9027)───pstree(9066)
│ ├─sshd(8256)───sshd(8321)───sftp-server(8323)
│ ├─sshd(8412)───sshd(8418)─┬─bash(8419)───a.out(8519)
│ │ └─bash(8927)───sleep(9065)
│ └─sshd(8416)───sshd(8482)───sftp-server(8483)
...
straceで実行されているシステムコールを確認してみる。 ※sleepは削除しています。 以下のstraceの結果からgetppidシステムコールとgetpidシステムコールが呼び出されていることがわかる。
[debug@localhost linux_system_program]$ strace ./a.out
execve("./a.out", ["./a.out"], 0x7ffe83528300 /* 26 vars */) = 0
brk(NULL) = 0x2234000
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f12661ba000
access("/etc/ld.so.preload", R_OK) = -1 ENOENT (そのようなファイルやディレクトリはありません)
open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=23339, ...}) = 0
mmap(NULL, 23339, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f12661b4000
close(3) = 0
open("/lib64/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\20&\2\0\0\0\0\0"..., 832) = 832
fstat(3, {st_mode=S_IFREG|0755, st_size=2156160, ...}) = 0
mmap(NULL, 3985888, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7f1265bcc000
mprotect(0x7f1265d8f000, 2097152, PROT_NONE) = 0
mmap(0x7f1265f8f000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1c3000) = 0x7f1265f8f000
mmap(0x7f1265f95000, 16864, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7f1265f95000
close(3) = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f12661b3000
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f12661b1000
arch_prctl(ARCH_SET_FS, 0x7f12661b1740) = 0
mprotect(0x7f1265f8f000, 16384, PROT_READ) = 0
mprotect(0x600000, 4096, PROT_READ) = 0
mprotect(0x7f12661bb000, 4096, PROT_READ) = 0
munmap(0x7f12661b4000, 23339) = 0
getppid() = 10308
fstat(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 0), ...}) = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f12661b9000
write(1, "Parent PID 10308\n", 17Parent PID 10308
) = 17
getpid() = 10310
write(1, "PID 10310\n", 10PID 10310
) = 10
exit_group(10) = ?
+++ exited with 10 +++
[debug@localhost linux_system_program]$
ltraceを実行してもgetppidとgetpidが表示されているのでライブラリの中からシステムコールがよびだされているのではないかと想像。 以下のページを確認すると頻繁にシステムコールを発行しないようにglibcがキャッシュするようです。
[debug@localhost linux_system_program]$ ltrace ./a.out
__libc_start_main(0x4005cd, 1, 0x7fff785b3258, 0x400600 <unfinished ...>
getppid() = 11134
printf("Parent PID %d\n", 11134Parent PID 11134
) = 17
getpid() = 11135
printf("PID %d\n", 11135PID 11135
) = 10
+++ exited (status 10) +++
[debug@localhost linux_system_program]$
manでも確認してみる。man getpidとman getppidは同じGETPID(2)というページが表示されます。 ※CentOSを最小構成でインストールした場合、以下のコマンドでmanをインストールする。 GETPIDの右に表示されている2はシステムコールを意味しています。
yum install man-pages
GETPID(2) Linux Programmer's Manual GETPID(2)
NAME
getpid, getppid - get process identification
SYNOPSIS
#include <sys/types.h>
#include <unistd.h>
pid_t getpid(void);
pid_t getppid(void);
DESCRIPTION
getpid() returns the process ID of the calling process. (This is often used by routines that generate unique temporary filenames.)
getppid() returns the process ID of the parent of the calling process.
ERRORS
These functions are always successful.
CONFORMING TO
POSIX.1-2001, 4.3BSD, SVr4.
NOTES
Since glibc version 2.3.4, the glibc wrapper function for getpid() caches PIDs, so as to avoid additional system calls when a process calls
getpid() repeatedly. Normally this caching is invisible, but its correct operation relies on support in the wrapper functions for fork(2),
vfork(2), and clone(2): if an application bypasses the glibc wrappers for these system calls by using syscall(2), then a call to getpid() in
the child will return the wrong value (to be precise: it will return the PID of the parent process). See also clone(2) for discussion of a
case where getpid() may return the wrong value even when invoking clone(2) via the glibc wrapper function.
SEE ALSO
clone(2), fork(2), kill(2), exec(3), mkstemp(3), tempnam(3), tmpfile(3), tmpnam(3), credentials(7)
COLOPHON
This page is part of release 3.53 of the Linux man-pages project. A description of the project, and information about reporting bugs, can be
found at http://www.kernel.org/doc/man-pages/.
Linux 2008-09-23 GETPID(2)
pid_tとはint型のようです。