제가 이해한 바에 따르면, 쉘에 "ls"와 같은 명령을 입력할 때마다 상위 프로세스(즉, 내 쉘)는 fork() 시스템 호출을 사용하여 자신을 복사한 다음 exec() 시스템 호출을 사용하여 대체합니다. 이 경우 "ls"가 종료되면 제어권이 내 쉘로 반환됩니다.
그러나 "ls"에서 strace를 실행하면 execve() 호출만 표시되고 포크는 표시되지 않으며 제어권은 여전히 내 쉘에 다시 제공됩니다. 여기서 좀 헷갈림...
$ strace ls
execve("/usr/bin/ls", ["ls"], 0x7ffd938934e0 /* 25 vars */) = 0
brk(NULL) = 0x1134000
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f6ea9e38000
access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory)
open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=23255, ...}) = 0
답변1
당신의 이해가 정확합니다. 실행할 때 strace ls
두 개의 포크도 있습니다 . 쉘은 자체적으로 분기되어 exec()
run 에 사용되며 strace
strace는 run 에 대해 동일한 작업을 수행합니다 ls
.
strace는 다음에서 발생하는 모든 시스템 호출을 인쇄하므로 strace 출력에 분기가 표시되지 않습니다.strace의 하위 프로세스그때쯤에는 이미 포크가 발생했습니다.
bash
포크 앤 실행strace
strace
포크상위 프로세스는
strace
모든 시스템 호출을 가로채기 위해 하위 프로세스에 연결됩니다.이 시점부터는 시스템 호출만 볼 수 있습니다.
아이들이 달릴
strace
때ls
사용execve()
strace
포크가 발생하는 것을 확인하는 한 가지 방법은 "외부에서" 연결하는 것입니다.
echo $$
쉘의 프로세스 ID를 얻는 데 사용됩니다.- 실행 시
strace -f --attach=PID
"PID"를 위의 프로세스 ID로 바꾸세요.다른 콘솔에서. ls
첫 번째 셸에서 실행- 다른 콘솔 창에는 쉘 및 분기된 하위 키에서 발생한 모든 시스템 호출(
fork()
/clone()
호출 포함) 이 표시됩니다. - strace를 중지하려면 두 번째 콘솔에서 CTRL+C를 사용하세요.
언급할 또 다른 점은 fork()
현재 Linux 커널에서는 이것이 clone()
시스템 호출을 사용하여 구현되므로 대신 strace 출력에서 이를 볼 수 있다는 것입니다 clone(…)
.fork()