12Day Study
[[[[[프로세스와 신호(Process and Signal)]]]]]
[root@waf ~]# ps -lf
F S UID PID PPID C PRI NI ADDR SZ WCHAN STIME TTY TIME CMD
4 S root 13443 13441 0 75 0 - 1466 wait 08:21 pts/1 00:00:00 -bash
4 R root 13666 13443 0 76 0 - 543 - 09:31 pts/1 00:00:00 ps -l
위에서 NI는 nice값이다 프로세서의 우선순위를 말함(높을 수록 높음 기본은 0)
nice 값 변경:
$nice < 프로세스명> &
nice 값 10으로 재설정:
$renice 10 < PID>
system을 이용한 새 프로세스 시작 예:
#include < stdlib.h>
#include < stdio.h>
int main()
{
system("ps -ax");
exit(0);
}
프로세스 이미지 교체하기(따른 PID가 안 생기고 실행됨):
#include < unistd.h>
int execl("bin/ps", "ps", "-ax", 0); => 반환값(에러 -1), errno 에러변수
프로세스 이미지 복제하기(fork) => 반환값(실패 -1), errno 에러변수
#include < sys/types.h>
#include < unistd.h>
pid_t fork(void);
!!중요!!
부모 프로세스에서 fork를 호출하면 새로운 자식 프로세서 PID를 반환하고 자식 프로세스에서 다시 fork를 하면 0을 반환한다
fork 예제: 608페이지 참조
프로세스 종료 기달리기(wait 시스템 호출은 부모 프로세스의 자식 프로세스 중 하나가 정지할 때까지 부모 프로세스를 일시 중지시킨다) => 반환값(정상 0)
#include < sys/types.h>
#include < sys/wait.h>
pid_t wait(int *stat_log);
wait 예: 611페이지 참조
좀비 프로세스(< defunct> 또는 < zombie>)
특정 프로세스 종료 기다리기
#include < sys/types.h>
#include < sys/wait.h>
pid_t waitpid(pid_t pid, int *stat_log, int options); => 종료하였거나 정지했으면 PID, 에러 -1, 종료안하거나 정지안했으면 0
입출력 리디렉션 예:
[root@waf cstudy]# cat upper.c
#include < stdio.h>
#include < ctype.h>
int main()
{
int ch;
while((ch=getchar()) != EOF) {
putchar(toupper(ch));
}
exit(0);
}
[root@waf cstudy]# ./upper
hahaha hohoho
HAHAHA HOHOHO
!!중요!!
리눅스에서 쓰레드를 프로그래밍하는 것은 여러 프로세스를 사용하는 것 만큼 흔하지 않다. 그 이유는 리눅스 프로세스는 경량이며, 협력하는 여러 프로세스를 프로그래밍하는 것이 쓰레드 프로그래밍보다 쉽기 때문이다
신호처리 하기 예:
#include < signal.h>
#include < stdio.h>
#include < unistd.h>
void ouch(int sig)
{
printf("OUCH! = I got signal %d\n", sig);
(void) signal(SIGINT, SIG_DEF); => SIG_DEF 기본 동작으로 복구, SIG_IGN 무시하기
}
int main()
{
(void) signal(SIGINT, ouch);
while(1) {
printf("Hello World!\n");
sleep(1);
}
}
$ ./ctrlc
Hello World!
Hello World!
Hello World!
Hello World!
^C => CTRL+C를 누른 시점
OUCH! - I got signal 2
Hello World!
Hello World!
Hello World!
Hello World!
^C => CTRL+C를 누른 시점
$
!!중요!!
signal보단 sigaction을 사용을 권한다
신호 보내기 => 우리가 아는 kill이긴 하지만 신호를 보낼 때도 이용됨
#include < sys/types.h>
#include < signal.h>
int kill(pid_t pid, int sig); => 반환값(실패 1)
알람
#include < unistd.h>
unsigned int alarm(unsigned int seconds);
!!중요!!
신호를 조심스럽게 프로그램밍해야 한다. 왜냐하면 신호를 사용하는 프로그램에서 발생할 수 있는 "경쟁 조건(race condition)"이 많기 떄문이다. 예를 들어 pause를 호출하여 신호를 기다리고자 할때 pause를 호출하기 전에 신호가 발생하면 프로그램은 일어나지도 않을 이벤트를 무한히 기다리는 수가 생긴다.
알람 예:
#include < sys/types.h>
#include < signal.h>
#include < stdio.h>
#include < unistd.h>
static int alarm_fired = 0;
void ding(int sig)
{
alarm_fired = 1;
}
int main()
{
pid_t pid;
printf("alarm app starting\n");
pid = fork();
switch(pid) {
case -1:
perror("fork failed");
exit(1);
case 0:
sleep(5); => 포크한 후에 자식 프로세서 일시정지 5초
kill(getppid(), SIGALRM); => 부모 프로세스에 SIGALRM 보내기
exit(0);
}
printf("waiting for alarm to go off\n");
(void) signal(SIGALRM, ding);
pause(); => SIGALRM이 올때까지 기달리다가 오면 ding함수 호출
if(alarm_fired) printf("Ding!\n"); => alarm_fired==1 이면 Ding! 출력
printf("done\n");
exit(0);
}
견고한 신호 프로그래밍
#include < signal.h>
int sigaction(int sig, const struct sigaction *act, struct sigaction *oact);
반환값(성공 0, 실패 -1)
sigaction 예: 627페이지 참조
2009년 3월 12일 목요일
피드 구독하기:
댓글 (Atom)
댓글 없음:
댓글 쓰기