치춘짱베리굿나이스
[Rank 2] Minitalk - 사용가능 함수 정리 본문
signal
void (*)(int) signal(int sig, void (*handler)(int));
- 시그널 처리 방법을 설정한다
- 몇몇 시그널들은 이미 정의된 행동을 함으로써 처리되는데, 이처럼 기존에 정의된 행동을 그대로 할 지, 시그널을 그냥 무시할지, 아니면 사용자 정의 행동을 하도록 바꿔줄 지 선택할 수 있다
sig
는 처리해줄 시그널 번호*handler
는 시그널을 처리해줄 핸들러SIG_IGN
을 인자로 넘겨주면 해당 시그널을 무시한다함수포인터
를 넘겨주면 시그널이 들어왔을 때 특정 함수를 호출한다SIG_DFL
을 인자로 넘겨주면 기존에 정의된 방법대로 수행한다
sigset_t 구조체
typedef struct {
unsigned int __sigbits[4];
} sigset_t;
시그널은 비트로 이루어져 있으며, 시그널 집합은 이러한 시그널을 비트 마스크로 표현해준다
만약 특정 비트값이 1이면 해당 위치에 대한 시그널이 설정되어 있다는 의미이고, 0이면 설정되어 있지 않다는 뜻
sigemptyset
int sigemptyset(sigset_t *set);
- 인자로 들어온 시그널 세트 (
sigset
) 를 초기화한다 *set
은 초기화해 줄 시그널 세트- 반환값은 무조건 0이다
sigaddset
int sigaddset(sigset_t *set, int signo);
- 인자로 들어온 시그널 (
signo
) 를 시그널 세트 (set
) 에 추가한다 *set
은 값을 넣을 시그널 세트signo
는 추가할 시그널 넘버- 반환값은 무조건 0이다
sigaction
int sigaction(int sig, const struct sigaction *restrict act, struct sigaction *restrict oact);
- 인자로 들어온 시그널 (
sig
)가 호출되었을 때 실행할 행동을 정의한다 sig
는 행동을 정의해 줄 시그널 종류act
는 행동이 정의된sigaction
타입 구조체oact
는 기존의 행동이 정의된sigaction
타입 구조체
sigaction (구조체)
struct sigaction {
int sa_flags;
union {
void (*sa_handler)();
void (*sa_sigaction)(int, siginfo_t *, void *);
};
sigset_t sa_mask;
}
// man 기준 sigaction 정의
struct sigaction {
union __sigaction_u __sigaction_u;
sigset_t sa_mask;
int sa_flags;
}
union __sigaction_u {
void (*__sa_handler)(int);
void (*__sa_sigaction)(int, siginfo_t *, void *);
};
#define sa_handler __sigaction_u.__sa_handler
#define sa_sigaction __sigaction_u.__sa_sigaction
sa_flags
는 다음과 같은 값이 들어오며,or
연산자를 이용하여 두 개 이상의 값을 한 번에 패러미터로 넘겨줄 수도 있다SA_NOCLDWAIT
: 시그널이 SIGCHLD이면 시스템은 자식 프로세스가 종료될 때 좀비 프로세스를 만들지 않는다SA_NOCLDSTOP
: 시그널이 SIGCHLD면 시스템은 자식 프로세스가 종료될 때 부모 프로세스에 SIGCHILD를 전달하지 않는다 (자식 프로세스가 SIGSTOP, SIGTSTP, SIGTTIN, SIGTTOU 등으로 인해 중단되어도 부모 프로세스가 이를 알 수 없다)SA_ONESHOT
: 시그널의 기본 처리 방법을 시스템 기본 설정인 SIG_DFL로 재설정 후, 시그널이 처리되는 동안 블록하지 않는다SA_ONSTACK
: 시그널 스택 (sigaltstack) 에 올라가 있는 프로세스로 시그널을 전달한다SA_RESETHAND
: 시그널의 기본 처리 방법을 시스템 기본 설정인 SIG_DFL로 재설정SA_RESTART
: 시그널을 받으면 시그널 처리 후 시그널 핸들러에 의해 중지된 기능을 재시작한다SA_NOMASK
: 시그널 핸들러가 실행되는 동안 (시그널을 처리하는 중)에는 전달된 시그널이 블록되지 않도록 한다SA_NODEFER
: 시그널 핸들러가 실행되는 동안 (시그널을 처리하는 중)에는 전달된 시그널이 블록되지 않도록 한다SA_SIGINFO
:sa_handler
에 해당하는 함수가 동작하지 않고,sa_sigaction
이 동작하며 더 다양한 인수를 받을 수 있다,sa_sigaction
이 받는 인자값은 시그널 번호, 시그널이 만들어진 이유, 시그널을 받는 프로세스의 정보이다.SIG_DFL
과SIG_IGN
이 사용될 땐 해당 비트를 사용하면 안 된다
sa_handler
는sigaction()
함수의 인자로 들어온sig
시그널이 발생했을 때 실행할 함수이며,signal()
함수에서 인자값으로 넣어주는 핸들러 함수가 여기에 들어간다sa_sigaction
은sa_flags
에SA_SIGINFO
가 설정되어 있을 때만 호출된다 (SA_SIGINFO
가 설정되어 있지 않으면sa_handler
가 호출되고,SA_SIGINFO
가 설정되어 있으면sa_sigaction
이 호출됨)sa_mask
는 시그널을 처리하는 동안 블록할 시그널 집합의 마스크이며, 시그널 핸들러 동작 중에, 다른 시그널들이 들어와도 블록할 수 있도록 막아준다. 이때sa_flags
에SA_NODEFER
를 설정하지 않으면 시그널 핸들러를 호출하게 한 시그널도 블록됨
kill
int kill(pid_t pid, int sig);
- 무시무시한 이름과는 다르게.. 죽이는 짓은 안하고 시그널만 전달해주는 얌전한 함수
pid
에 시그널을 받을 프로세스의 id가 들어간다- pid가 0보다 클 경우: 해당 pid에 시그널이 보내짐
- pid가 0일 경우: 시그널을 보낸 프로세스와 같은 그룹에 속한 (그룹아이디가 같은) 모든 프로세스에 시그널이 보내짐
- pid가 -1일 경우:
- 유저가 관리자 권한을 가지고 있다면 (Superuser privilege) 시스템 프로세스와 현재 시그널을 전송하려는 프로세스를 제외한 모든 프로세스에 시그널을 전송
- 유저가 관리자 권한을 가지고 있지 않다면, 해당 유저와 같은 uid를 가진 프로세스에만 현재 시그널을 전송
sig
에 해당 프로세스에 보낼 시그널이 들어간다sig에 0을 넣을 경우 에러 체킹을 시도하며, pid의 유효성을 검사할 수 있다- 이때 인자값으로 들어갈 signal은
sigaction()
에 이미 정의되어 있어야 함 - 정상적으로 kill 함수가 수행되면 0을 리턴, 에러 발생 시에는 -1 리턴 및 errno 세팅됨
exit
void exit(int status);
- 프로세스를 종료한다 (커널 종료 작업)
- 커널 종료 작업 시에는 프로세스가 사용하던 메모리 (malloc 되었거나.. 뭐 지역변수나.. static...) 를 모두 해제하고, 파일 디스크립터를 모두 닫는다
malloc
void *malloc(size_t size);
- 힙 메모리에
size
만큼의 메모리를 동적으로 할당하고, 해당 주소값을 반환한다
free
void free(void *ptr);
malloc
,calloc
등으로 할당한 메모리를 해제한다
sleep
unsigned int sleep(unsigned int seconds);
seconds
초만큼 스레드를 일시정지한다 (대기 상태). 만약sleep
중간에 시그널이 발생하면 바로 복귀 후 남은 시간이 반환된다- 만약 15초를 쉬는 중에 (
seconds
= 15) 5초만에 시그널이 발생하여 복귀하였을 경우, 리턴값은 10
usleep
int usleep(useconds_t microseconds);
microseconds
마이크로초만큼 스레드를 일시정지한다 (대기 상태)- 나머지는
sleep
과 동일
write
ssize_t write(int fd, const void *buf, size_t count);
- 우리의 오랜 친구.. 출력을 도와주는 write
fd
는 파일 디스크립터 (문자열을 적을 위치, 0은 표준입력 1은 표준출력)count
는 출력할 문자열의 길이*buf
는 출력할 문자열의 주소
getpid
pid_t getpid(void);
- 현재 프로세스의 아이디를 리턴한다현재 프로세스의 부모 프로세스 아이디를 리턴하는
getppid()
도 있으나 뭐 여기선 안쓰니까... - 아이디는 모든 프로세스가 다 고유한 값을 가지기 때문에 임시 파일명을 지을 때 좋다고 man이 말한다
getpid
와getppid
는 무조건 성공하기 때문에 (프로그램을 구동한다는 건 반드시 개별적인 프로세스가 동작하는 것과 같으니까 애초에 해당 함수를 불러오는 시점에서 프로세스 아이디는 무조건 존재) 실패했을 경우에 반환하는 값은 없다
pause
int pause(void);
kill()
함수나 내부 타이머 (setitimer()
참고) 에 의해 시그널을 받기 전까지 현재 스레드를 일시정지시킨다pause()
를 통해 스레드가 일시정지된 상태에서 시그널 처리기 (signal handler) 가 멈출 경우pause()
는 리턴값을 뱉는다고 한다- 어떤 경우에서든 무조건 -1을 리턴한다
'42 > 42s Cursus' 카테고리의 다른 글
[Rank 2] Minitalk 구현 (Bonus) (4) | 2021.09.25 |
---|---|
[Rank 2] Minitalk 구현 (Mandatory) (0) | 2021.09.25 |
[Rank 2] Minitalk (0) | 2021.09.25 |
[Rank 3] Philosophers 반성회 (4) | 2021.09.13 |
[Rank 3] Philosophers - 사용가능 함수 정리 [Mandatory] (0) | 2021.09.04 |
Comments