Search
Duplicate
🗣️

minitalk (1) 허용 함수

간단소개
팔만코딩경 컨트리뷰터
ContributorNotionAccount
주제 / 분류
C
42cursus
minitalk
태그
Scrap
8 more properties
minitalk
반환 값과 에러 상황에 대한 자세한 내용은 man 확인을 권장합니다.

기존 함수

ft_printf
malloc
free
write
exit

신규 함수

getpid
sleep
usleep
pause
kill
sigemtpyset
sigaddset
signal
sigaction

<unistd.h>

PID 출력

getpid 함수는 항상 성공하므로 에러 처리가 불필요하다.
pid_t getpid(void); // 호출 프로세스의 PID 반환
C

스레드 정지

unsigned int sleep(unsigned int seconds); // 설정된 만큼 대기 (초 단위) int usleep(useconds_t microseconds); // 설정된 만큼 대기 (마이크로초 단위) int pause(void); // 시그널이 올 때 까지 대기
C
함수
RETURNS
sleep(3)
내부적으로 nanosleep(2)을 입력된 초 만큼 호출하여 대기한다. 0 : 성공 > 0 : 시그널 캐치 후 남은 대기 시간
usleep(3)
내부적으로 nanosleep(2)을 입력된 마이크로 초 만큼 호출하여 대기한다. 0 : 성공 -1 : EINTR(시그널 캐치)
pause(2)
시그널이 캐치될 때까지 대기한다. -1 : EINTR(시그널 캐치)

<signal.h>

시그널 전송

int kill(pid_t pid, int sig); // 지정된 프로세스로 지정된 시그널 전송
C
pid
pid > 0 지정 프로세스로 시그널 전송
pid == 0 호출 프로세스 그룹의 모든 프로세스로 시그널 전송
pid == -1 호출 프로세스 그룹의 모든 프로세스로 시그널 전송 (본인 제외)
pid < -1 지정 프로세스 그룹의 모든 프로세스로 시그널 전송
반환값
0 : 성공
-1 : EINVAL (유효하지 않은 시그널)
-1 : EPERM (호출 프로세스에서 목표 프로세스에 시그널을 보낼 권한 없음)
-1 : ESRCH (목표 프로세스 또는 그룹이 존재하지 않음)

시그널 집합 설정

반환값
1 : sigismember 함수의 set 멤버가 시그널인 경우
0 : 성공
int sigemptyset(sigset_t *set); // 시그널 집합에서 모든 시그널 제거 int sigaddset(sigset_t *set, int signo); // 시그널 집합에서 특정 시그널 추가
C

시그널 등록

signal : 시그널 처리를 결정하는 간단한 함수 (운영체제에 따라 다른 동작)
sigaction : 시그널 처리를 결정하는 상세한 함수 (운영체제 차이가 없어 안정적)
#include <signal.h> typedef void (*sig_t) (int); void (*signal(int sig, void (*func)(int)))(int); sig_t signal(int sig, sig_t func); int sigaction(int sig, \ const struct siaction *restrict act, \ // 새로운 시그널 정보 등록 struct sigaction *restric oact); // 기존의 시그널 정보 백업
C
반환값
0 : 성공
-1 : EINVAL (유효하지 않은 시그널)
-1 : EFAULT (유효하지 않은 메모리 act, oact)

시그널 예시

서버가 잘 동작하는지 killbc를 활용하여 테스트할 수 있다.
$ kill -l # 시그널 목록 확인 $ kill -USR1 <pid> # SIGUSR1 (10)전달 $ kill -USR2 <pid> # SIGUSR2 (12)전달
Shell
$ man ascii $ bc <<< "obase=2; 65" # 'A' 1000001 $ bc <<< "obase=10; ibase=2; 1000001" 65 # 문자 'A' 출력 $ kill -USR2 <pid> # 0 $ kill -USR1 <pid> # 1 $ kill -USR2 <pid> # 0 $ kill -USR2 <pid> # 0 $ kill -USR2 <pid> # 0 $ kill -USR2 <pid> # 0 $ kill -USR2 <pid> # 0 $ kill -USR1 <pid> # 1
Shell

signal

#include <stdio.h> #include <signal.h> static volatile sig_atomic_t g_signal; void ft_handler(int sig) { g_signal = sig; } int main(void) { // 시그널 호출되었을 때 수행될 시그널 핸들러 등록 (커널에 등록됨) signal(SIGUSR1, ft_handler); signal(SIGUSR2, ft_handler); // 시그널 호출까지 대기 while (1) { if (g_signal == 0) continue ; printf("pid[%d] signal[%d]\n", NULL, g_signal); g_signal = 0; } return (0); }
C

sigaction

#include <stdio.h> #include <signal.h> static volatile sig_atomic_t g_pid; static volatile sig_atomic_t g_signal; void ft_handler(int sig, siginfo_t *info, ucontext_t *uap) g_pid = info->si_pid; g_signal = sig; } int main(void) { struct sigaction act; // 시그널이 호출되었을 때 블록될 시그널 설정 sigemptyset(&act.sa_mask); sigaddset(&act.sa_mask, SIGUSR1); //block SIGUSR1 sigaddset(&act.sa_mask, SIGUSR2); //block SIGUSR2 // 시그널 처리를 위한 핸들러 설정 act.sa_flags = SA_SIGINFO | SA_RESTART; act.sa_sigaction = ft_handler; // SA_SIGINFO가 지정된 경우에 사용되는 핸들러 act.sa_handler = NULL; // SA_SIGINFO가 지정되지 않은 경우 사용되는 기본 핸들러 // 시그널 호출되었을 때 수행될 시그널 정보 등록 (커널에 등록됨) sigaction(SIGUSR1, &act, NULL); sigaction(SIGUSR2, &act, NULL); // 시그널 호출까지 대기 while (1) { if (g_signal == 0) continue ; printf("pid[%d] signal[%d]\n", g_pid, g_signal); g_signal = 0; } return 0; }
C
Prev