signal 과 관련된 코딩 문제입니다.

neon20의 이미지

#include<stdio.h>
#include<unistd.h>
#include<sys/wait.h>
#include<sys/types.h>

int pid1,pid2;

void handler(int num){
switch(num){
case SIGUSR1:
if(pid1 == getpid()){
printf("SIG1,pid = %d\n",getpid());
printf("pid2 = %d\n",pid2);
//kill(pid2,SIGUSR1);
}else{
printf("SIG1,pid = %d\n",getpid());
exit(0);
}
exit(0);
case SIGUSR2:
printf("SIG2,pid = %d\n",getpid());
default: break;
}
}

int main(){
int status;
signal(SIGUSR1,handler);
signal(SIGUSR2,handler);
pid1 = getpid();
/*자식 프로세스*/
if( (pid2 = fork()) == 0){
printf("This is child. %d, sending SIGUSR1\n",getpid());
kill(pid1,SIGUSR1);
}else{
/*부모 프로세스*/
printf("This is parent. %d\n",pid1);
}
printf("done - pid=%d\n",getpid());
return 0;
}
////////////////////////////////////////////////
제가 프로그램에서 예상하는 결과값은

This is child. 18792, sending SIGUSR1
done - pid=18792
SIG1,pid = 18791
pid2 = 0 <- 이곳엔 자식프로세스의 값이 나옴

대충 이런 형태 입니다. 그런데 pid2에 계속 0값이 나오네요.. 그 이유가 뭔가요... :(
그리구 부모 프로세스의 코드는 전혀 수행이 되지 않는거 같은데 그 이유도 설명해주시면 감사하겠습니다..

wariua의 이미지

새 생명을 힘들게 낳느라 아직 정신이 돌아오지 않은 부모에게 자식이 너무 매몰차게 신호를 날리고 있는 것 같습니다. pid2에 자식의 이름 석자도 기록 못 한 상태인데... 흑흑- 범죄는 아니지만 굉장히 비도덕적인 행위입니다.

꼭 이렇게 자식이 성질 급하게 시그널을 날려야 한다면, 그리고 시그널 핸들러에서 부모가 자식의(혹은 시그널 날린 넘의) pid를 알고 있어야 한다면, signal() 대신 sigaction()의 사용은 어떨까요? sa_sigaction에 등록한 핸들러에선 siginfo_t.si_pid로 시그널을 날린 프로세스의 pid를 알 수 있습니다.

부모 프로세스의 코드가 전혀 수행되지 않는 건... 정신도 들기 전에 매몰찬 자식의 시그널을 받고서,

Quote:
내 자식의 이름 따윈 나도 모른... 헉-

이라는 한맺힌 유언을 남기고 세상을 떠나버리기 때문이겠지요. 삼가 조의를 표합니다... :cry:

$PWD `date`

gestate의 이미지

if( (pid2 = fork()) == 0){

여기에서 당연히 if((pid2 = 0) == 0) 임을 체크했기 때문에
pid는 당연히 0 이겠죠..

아직도 세상은 살만한 가치가 있나(?)

neon20의 이미지

여러가지 도움말 감사드립니다.. :) 말씀을 들어보니 제가 생각했던 것 처럼 자식이 시그널을 부모에게 보낸후 핸들러는 부모프로세스에서 돌아가는게 맞는거 같네요.

Quote:
부모 프로세스의 코드가 전혀 수행되지 않는 건... 정신도 들기 전에 매몰찬 자식의 시그널을 받고서,
인용:
Quote:
내 자식의 이름 따윈 나도 모른... 헉-

이라는 한맺힌 유언을 남기고 세상을 떠나버리기 때문이겠지요. 삼가 조의를 표합니다...


비유가 너무 재밌네요.. :wink: 한데 비유가 추상적이어서...ㅜㅜ 부모프로세스가 죽는 상황이 구체적으로 어느 코드에서 유발되는 것인가요? 그리구 부모프로세스가 자식의 이름(pid2)를 아직 모르는 이유가 무었인가요? 마지막으로.. (너무 궁금한게 많아요..ㅜㅜ) 자식 프로세스가 너무 급하게 신호를 보낸다고 하셨는데 조금 덜 급하게 보내려면 다른 방법이 있나요..?
neon20의 이미지

헉.. 자식프로세스에서 시그널을 보내기 전에 sleep()를 해주니 되는군요..ㅜㅜ 감사드립니다. 그런데 fork() 호출뒤 동시에 자식 프로세스와 부모 프로세스의 pid2에 값이 배정되는것은 아니군요..그런데 부모 프로세스가 죽게되는 상황이 발생하는 이유가 아직 배정받지 못한 pid2의 값을 물어보기 때문인가요?

wariua의 이미지

왜 부모가 자식의 이름 석자를 모르고 있냐 하는 건...

fork() 함수를 호출할 때는 프로세스가 하나이지만, 함수의 실행 결과로 동일한 프로세스 하나가 더 생깁니다. (흠... 이분법으로 자식을 낳는 걸 보면 프로세스란 건 대략 아메바스럽군요-) 이제 자식과 부모는 각각 별개로 동작합니다. 새로 생긴 자식 프로세스는 fork()의 결과값(0)을 pid2에 저장하고, 그걸 0과 비교하고, 잠시 후 부모에게 시그널을 날립니다.

한편 그때 부모는... 아직 fork() 호출에서 반환조차 되지 않은 상태일 수 있습니다. fork()에서 반환이 되지 않았으니 그 결과값을 알지 못하고, 그러니 pid2에는 아무것도 저장을 하지 못한 상태입니다. 확인을 위해 fork() 하기 전에,

pid2 = 11111;

라고 해두면, 부모 프로세스에서는 fork()의 결과값이 미처 저장되기도 전에 시그널 핸들러가 실행되므로 출력 결과가 요렇게 됩니다.
Quote:

This is child. 18792, sending SIGUSR1
done - pid=18792
SIG1,pid = 18791
pid2 = 11111 <= 요렇게요...

자식 프로세스가 한참을 실행한 후에도 부모 프로세스는 아직 fork()에서 반환조차 하지 않은 상태... 라는 게 항상 성립하지는 않습니다. 커널 내의 fork() 시스템콜 구현 방식에 따라서(즉, 프로세스를 새로 만든 다음에 부모와 자식 중 어느 쪽을 먼저 실행할 것인가에 대한 정책), 그리고 현재 시스템의 로드, 등등에 따라 예측 불가능한 결과가 나올 수 있습니다. 그래서 정히 시그널 핸들러에서 자식 프로세스의 pid를 알아야 한다면 sigaction()의 사용을 추천드린 것이구요-

sleep()으로 시그널을 날리는 시점을 늦추는 건 웬간한 경우에는 문제가 해결된 것처럼 동작하지만 특수한 경우에는 여전히 문제가 발생할 수 있습니다. 가령, 시스템 로드가 무지막지하여 자식 프로세스가 잠시 눈 붙이고 났더니 sleep()에서 지정한 시간이 다 흘러 버렸고, 그 사이에 다른 프로세스들만 열심히 실행되고 여전히 부모는 fork()에서 반환되지 않은 상태에서 다시 자식 프로세스가 실행돼 버리면, 같은 결과가 되겠죠.

왜 부모가 죽는가 하는 건... 핸들러 함수의 SIGUSR1 처리 루틴의 마지막에 exit(0)가 있어서...가 아닐까요;;

$PWD `date`

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.