-
[Linux] 멀티 Process, Signal, WDT프로그래밍/리눅스 시스템 2024. 4. 15. 01:30
process 관련 리눅스 명령어
프로세스 확인 명령어 (list 형태)
$ ps -ef
- e : 모든 사용자들이 구동 시킨 모든 프로세스를 보여준다.
- f : 상세 정보를 출력한다. (full format)
grep과 함께 사용하여 특정 프로세스에 대한 정보만 확인 가능
$ ps –ef | grep [검색 프로그램명]
프로세스 확인 명령어 (tree 형태)
$ pstree
htop (프로세스 뷰어이자 프로세스 관리자) 실행하기
- 설치
$ sudo apt install htop –y
- 실행
$ htop
현재 쉘에서 실행 시킨 background 작업의 목록 출력
$ jobs
background 프로세스를 포어 그라운드로 실행
$ fg %숫자
Multi process
fork() : 자식 프로세스 생성
pid_t fork(void)
- 기능 : 자식 프로세스를 생성
- 입력값 : 없다. (void)
- 반환값 : pid_t 타입, 생성한 자식 프로세스의 PID 값을 반환 (자식 process에서는 0이 반환된다)
- 필요 라이브러리 : #include <sys/types.h> & #include <unistd.h> 필요
💡[참고] 프로세스의 종료 과정
- 프로세스가 종료된다. → State : Zombie 로 진입
- 아직 Process Descriptor가 남아있음
- 부모가 Descriptor를 제거 하기 전까지는 자식은 Zombie 상태로 머무름
- 자식 프로세스는 부모 프로세스에게 SIGCHLD Signal 을 보내 처리해줄 것을 요청함.
- 부모 프로세스는 SIGCHLD Signal을 받으면, 다음의 두 과정 중 하나를 수행함
- 자식 프로세스의 자원이 정리될 때까지 기다려야 한다면, wait( ) System Call 호출한다. → 커널이 정리한다.
- 자식 프로세스가 종료되는 것을 기다리지 않을 수 있다. (비동기적)
즉,
- 프로세스가 종료되면, 프로세스가 점유한 메모리를 정리해야 한다.
- 이때, 종료된 프로세스가 스스로 메모리를 정리하는 것이 아니라, 해당 프로세스의 부모 프로세스가 자원을 정리한다.
- 이때, 종료되었음에도 불구하고 부모 프로세스가 처리해주지 않아 여전히 프로세스 테이블에 존재하는 상태를 Zombie상태라 한다.
getpid() : 본인 프로세스의 pid를 반환
pid_t getpid(void)
getppid() : 부모 프로세스의 pid를 반환
pid_t getppid(void)
signal() : 시그널을 받는 함수.
ighandler_t signal(int signum, sighandler_t handler);
- 기능 :
- 입력 값
- signum : 시그널 번호. (매크로로 정의되어 있다.)
[signum 예시]
> SIGSTOP (19): 프로세스를 멈춘다. (T 상태).
> SIGKILL (9): 프로세스를 강제로 종료시킨다.
> SIGTERM (15): 프로세스에게 종료를 요청한다.
> SIGINT (2): 인터럽트 신호를 보낸다 (=> 주로 Ctrl+C로 보낸다.)
> SIGSEGV (11): 세그멘테이션 위반, 잘못된 메모리 접근
> SIGHUP (1): 터미널 연결 손실 또는 로그아웃 시그널.
> SIGUSR1 (10): 사용자 정의 신호 1.
> SIGUSR2 (12): 사용자 정의 신호 2.
> SIGPIPE (13): 파이프 끊김 신호.
> SIGALRM (14): 알람 신호, 타이머 만료를 나타낸다. - handler : 시그널이 발생하면, 동작할 함수포인터. 해당 함수는 매개변수로 signum을 받아온다.
- signum : 시그널 번호. (매크로로 정의되어 있다.)
- 반환값 : 해당 시그널에 대해 등록된 핸들러 함수 포인터
- 필요 라이브러리 : <signal.h>
ex) signal 수신
#include <stdio.h> #include <signal.h> #include <unistd.h> void run(int num){ printf("HO!\n"); } int main(){ signal(SIGUSR1, run); //signal() system call함수 : SIGUSR1이 오면, run 함수를 수행한다. pid_t pid = getpid(); printf("My PID : %d\n", pid); //본인의 pid를 출력한다. while(1) { printf("HAHIHUHEHO!\n"); //print를 계속 수행한다. sleep(1); } return 0; }
kill() : 시그널을 보내는 함수
int kill(pid_t pid, int sig);
- 기능 : 프로세스에 시그널을 보낸다.
- 입력값
- pid : 시그널을 보낼 프로세스의 pid
(🚨 프로세스의 pid는 실행될 때마다 변하기 때문에, 시그널을 받을 프로그램을 실행시켜 해당 프로세스의 pid를 확인한 뒤 알맞게 입력해야한다!) - sig : pid 프로세스에게 보낼 signum
- pid : 시그널을 보낼 프로세스의 pid
- 반환값 : 시그널 전송에 성공하면 0, 실패하면 -1을 반환
- 필요 라이브러리 : <sys/types.h> & <signal.h>
또는, command 창에서 signal을 직접 보낼 수도 있다.
$ kill -[보낼 시그널 번호] [시그널을 받을 프로세스의 pid]
ex) signal 송신
#include <stdio.h> #include <signal.h> #include <sys/types.h> #include <stdlib.h> int main() { //gogo 를 먼저 실행해서 pid를 확인 한 뒤 수정해서 빌드한다. pid_t target_pid = 865532; int ret = kill(target_pid, SIGUSR1); // system call 로 gogo 에게 SIGUSR1 을 보낸다. //전송 성공시 0을 반환, 실패는 -1 if (ret == 0) { //전송 성공 printf("%d <- signal transmit!\n", target_pid); } else { //전송 실패 printf("Fail!\n"); exit(1); } return 0; }
WDT (watch dog timer)
alarm() : SIGALRM 시그널을 전송
unsigned int alarm(unsigned int seconds)
- 기능 : seconds 시간이 지나면, SIGALRM 시그널을 전송하게 한다.
- 입력값 : seconds(초)
- 반환값 : 이전에 설정된 알람 시간(초) (*만약 이전에 알람이 설정되어 있지 않았다면, 0이 반환됨)
- 필요 라이브러리 : <unistd.h>
ex) SIGALRM 시그널 전송
#include <stdio.h> #include <signal.h> #include <stdlib.h> #include <unistd.h> void gogo(){ printf("WAKE UP!\n"); exit(1); } int main(){ signal(SIGALRM, gogo); printf("3 seconds\n"); alarm(3); //WDT printf("wait....\n"); while(1) sleep(1); //process die.. SEGFAULT Error return 0; }
'프로그래밍 > 리눅스 시스템' 카테고리의 다른 글
[Linux Kernel] Device Driver : Timer (0) 2024.04.29 [Linux Kernel] Device Driver : proc file system (0) 2024.04.29 [Linux Kernel] Device File : Read, write (with ioctl) (0) 2024.04.29 [Linux Kernel] Device Driver 적재, Device File 생성 (0) 2024.04.29 [Linux] 파일 입출력 함수 (0) 2024.04.14