13. 리눅스 프로세스 원리
- 프로세스 구조
- 텍스트(text) 영역 or 코드(code) 영역
- 프로세스가 실행하는 실행 코들르 저장하는 영역
- 데이터(data) 영역 or bss 영역
- 전역 변수, 정적 변수를 저장하는 메모리
- 힙(heap) 영역
- 동적 메모리 할당을 위한 영역
- 스택(stack area) 영역
- U(user area) 영역
- 프로세스의 내부 정보를 저장하는 영역
- 열린 파일의 디스크립터, 현재 작업 디렉터리 등을 저장
- 텍스트(text) 영역 or 코드(code) 영역
- size : 실행 파일의 각 영역의 크기를 알려줌
123whan@HappyLinux:~/C$ size /bin/lstext data bss dec hex filename124042 4728 4832 133602 209e2 /bin/ls - 프로세스 ID
- 쉘의 명령어 처리 과정
- 프롬프트를 내고 명령어를 입력 받음
- 자식 프로세스 생성
- 자식 프로세스에게 명령어를 실행시킴
- myps.c
1234567891011#include <stdio.h>#include <unistd.h>int main(){printf("Hello !\n");printf("나의 프로세스 번호 : [%d] \n", getpid());printf("내 부모 프로세스 번호 : [%d] \n", getppid());system("ps");} - 실행 결과
12345678910whan@HappyLinux:~/C$ ./mypsHello !나의 프로세스 번호 : [19269]내 부모 프로세스 번호 : [3025]PID TTY TIME CMD3025 pts/0 00:00:00 bash19141 pts/0 00:00:05 gedit19269 pts/0 00:00:00 myps19270 pts/0 00:00:00 sh19271 pts/0 00:00:00 ps
- 쉘의 명령어 처리 과정
- fork()
- 부모 프로세스를 똑같이 복제하여 새로운 자식 프로세스를 생성
- 자기 복제
- fork()는 한 번 호출되면 두 번 리턴
- 자식 프로세스에게는 0을 리턴하고
- 부모 프로세스에게는 자식 프로세스 ID 리턴
- 부모 프로세스와 자식 프로세스는 병행적으로 각각 실행을 계속한다.
- myfork.c
1234567891011#include <stdio.h>#include <unistd.h>/* 자식 프로세스를 생성한다. */int main(){int pid;printf("[%d] 프로세스 시작 \n", getpid());pid = fork();printf("[%d] 프로세스 : 반환값 %d\n", getpid(), pid);}
1234whan@HappyLinux:~/C$ ./myfork[19401] 프로세스 시작[19401] 프로세스 : 반환값 19402[19402] 프로세스 : 반환값 0 - myfork2.c
12345678910111213141516#include <stdlib.h>#include <stdio.h>/* 부모 프로세스가 자식 프로세스를 생성하고 서로 다른 메시지를 프린트 */int main(){int pid;pid = fork();if (pid ==0) { // 자식 프로세스printf("[Child] : Hello, world pid=%d\n", getpid());}else { // 부모 프로세스printf("[Parent] : Hello, world pid=%d\n", getpid());}}
123whan@HappyLinux:~/C$ ./myfork2[Parent] : Hello, world pid=19421[Child] : Hello, world pid=19422
- wait() : 프로그램 정지
1234#include <sys/types.h>#include <sys/wait.h>pid_t wait(int *status); - exec() : 프로그램 실행
- exec() 호출이 성공하면 리턴할 곳이 없어진다.
- 성공한 exec() 호출은 절대 리턴하지 않는다.
-
123456789#include <unistd.h>int execl(char* path, char* arg0, char* arg1, ... , char* argn,NULL)int execv(char* path, char* argv[ ])int execlp(char* file, char* arg0, char* arg1, ... , char* argn,NULL)int execvp(char* file, char* argv[ ])
- myexec.c
12345678910#include <stdio.h>#include <unistd.h>/* echo 명령어를 실행한다. */int main( ){printf("시작\n");execl("/bin/echo", "echo", "hello", NULL);printf("exec 실패!\n");}
123whan@HappyLinux:~/C$ ./myexec시작hello - myexec2.c
12345678910111213141516171819202122#include <stdio.h>#include <stdlib.h>#include <unistd.h>/* 자식 프로세스를 생성하여 echo 명령어를 실행한다. */int main( ){int pid, child, status;printf("부모 프로세스 시작\n");pid = fork();if (pid == 0) {execl("/bin/echo", "echo", "hello", NULL);fprintf(stderr,"첫 번째 실패");exit(1);}else {child = wait(&status);printf("자식 프로세스 %d 끝\n", child);printf("부모 프로세스 끝\n");}}
12345whan@HappyLinux:~/C$ ./myexec2부모 프로세스 시작hello자식 프로세스 19455 끝부모 프로세스 끝
- myargc.c
123456789#include <stdio.h>/* 모든 명령줄 인수를 프린트한다. */int main(int argc, char *argv[]){for (int i = 0; i < argc; i++) /* 모든 명령줄 인수 프린트 */printf("argv[%d]: %s \n", i, argv[i]);return 0;} - ps -ef :
- ps -aux
- pstree : 실행중인 프로세스들의 부모, 자식 관계를 트리 형태로 출력
123456789101112131415whan@HappyLinux:~/C$ pstreesystemd─┬─ModemManager───2*[{ModemManager}]├─NetworkManager─┬─dhclient│ └─2*[{NetworkManager}]├─accounts-daemon───2*[{accounts-daemon}]├─acpid├─apache2───5*[apache2]├─avahi-daemon───avahi-daemon├─bluetoothd├─boltd───2*[{boltd}]├─colord───2*[{colord}]├─cron├─cups-browsed───2*[{cups-browsed}]├─cupsd├─dbus-daemon
- w : 로그인한 사용자의 자세한 작업 정보를 출력
1234whan@HappyLinux:~/C$ w20:52:10 up 6:11, 1 user, load average: 1.26, 1.09, 0.89USER TTY FROM LOGIN@ IDLE JCPU PCPU WHATwhan :0 :0 23:41 ?xdm? 3:04 0.01s /usr/lib/gdm3/g