2014-12-29 16 views
2

EDEADLK를 올바르게 처리해야합니다. 내 프로그램에서 나는 두 아이들이 부모 수면까지 기다린 다음, 자물쇠를 적용하고 곧바로 떠나라고 봅니다. 미안하다. 나는 스페인 학생이다. 교착 상태에 대한여러 프로세스가 F_SETLKW를 사용하여 동일한 fd를 잠그면 교착 상태 (EDEADLK)가 표시되지 않는 이유는 무엇입니까?

int main(){ 

    pid_t childpid, childpid2; 

    struct flock cerrojo; 
    int fd, status; 

    if ((fd=open("prueba", O_RDWR)) == -1) 
     perror("apertura fallo"); 

    cerrojo.l_type =F_WRLCK; 
    cerrojo.l_whence =SEEK_SET; 
    cerrojo.l_start =0; 
    cerrojo.l_len =0; 

    if (fcntl(fd, F_SETLK,&cerrojo) == -1) 
     perror("cerrojo fallo"); 

    if ((childpid= fork()) == -1) { 
     printf("Could not create child"); 
     exit(-1); 
    } 

    if(childpid){ 

     if ((childpid2= fork()) == -1) { 
      printf("Could not create child"); 
      exit(-1); 
     } 

     if(childpid2){ 

      cerrojo.l_type = F_UNLCK; 
      cerrojo.l_whence =SEEK_SET; 
      cerrojo.l_start =0; 
      cerrojo.l_len =0; 

      sleep(2); 

      fcntl(fd, F_SETLKW, &cerrojo); 

      waitpid(childpid,&status,0); 
      waitpid(childpid2,&status,0); 

     } 


    } 

    if(!childpid||!childpid2){ 

     printf("Soy el hijo %d\n",getpid()); 

     if(fcntl(fd, F_SETLKW,&cerrojo) == -1){ 
      printf("FCNTL FALLA EN PID: %d\n",getpid()); 
      sleep(1); 
     } 

     printf("PID %d va a quitar el cerrojo.\n",getpid()); 

     cerrojo.l_type = F_UNLCK; 
     cerrojo.l_whence =SEEK_SET; 
     cerrojo.l_start =0; 
     cerrojo.l_len =0; 

     fcntl(fd, F_SETLKW, &cerrojo); 

     printf("HIJO ACABADO\n"); 

    } 

    return 0; 

} 
+0

"그 오류"_which_ 오류? 무슨 일이 일어날 것으로 예상됩니까? 대신 무엇이 발생합니까? 프로그램을 추적하려고 했습니까 ('strace -f')? 무슨 일이 일어나는 걸까요? –

+0

edeadlk가 커널이 교착 상태를 피하는 방법을 알아야합니다. –

+0

적어도 어떤 일이 일어나고 있는지, 어떻게 그것이 당신의 기대와 다른지 생각해보십시오. linux'strace -r -f -etrace = fcntl '은 많은 정보를 제공하지만 프로그램 출력만으로도 도움이 될 것입니다 :-) –

답변

0

당신은 적어도 잠금이 필요합니다. 나는 방 A의 열쇠와 방 B의 열쇠 그리고 방 A의 열쇠를 가진 다른 사람을 상상한다.

귀하의보기에 오직 하나의 잠금이있다 : 같은 큰 "문"(전체 파일). 두 번째 사람은 첫 번째 잠금을 해제하고 다음 동일한 노래 노래 자물쇠, 수면, ... 잠금을 해제 때까지 차단됩니다. 교착 상태가 발생하지 않습니다.

지금, 아래의 예에서, 부모의 잠금 "문"- fd 점 (? BTW, 당신 예를 들어이 정말 필요합니다)에 파일의 제 1 및 제 2 바이트 후 두 아이를 생성합니다. 두 자식은 두 바이트를 모두 잠그려고 시도하지만 각각 다른 바이트로 시작합니다. 부모가 두 바이트를 모두 해제하자마자 아이들은 잠금을 4 번 시도하지만 모든 잠금 시도는 4 번 시도하지만 마지막 하나는 교착 상태를 일으키고 EDEADLK으로 실패합니다. 따라서 현명하고 정당한 커널 덕분에 모든 사람이 행복하게 살 수 있습니다.

#include <stdio.h> 
#include <unistd.h> 
#include <fcntl.h> 
#include <stdlib.h> 
#include <string.h> 
#include <errno.h> 

int main(){ 

    pid_t childpid, childpid2; 

    struct flock cerrojo; 
    int fd, status; 

    if ((fd=open("prueba", O_RDWR)) == -1) 
     perror("apertura fallo"); 

    cerrojo.l_type = F_WRLCK; 
    cerrojo.l_whence = SEEK_SET; 
    cerrojo.l_start = 0; 
    cerrojo.l_len = 2; /* lock "doors" (i.e. bytes) 0 and 1*/ 

    if (fcntl(fd, F_SETLK,&cerrojo) == -1) 
     perror("cerrojo fallo"); 


    if((childpid= fork())){ /* parent */ 
     if ((childpid2= fork())) { /* still parent */ 

      cerrojo.l_type = F_UNLCK; 
      cerrojo.l_len = 2; /* unlock both doors: let the fun begin :-) */ 

      sleep(2); 
      printf("Tata va a quitar el cerrojo....\n",getpid()); 
      fcntl(fd, F_SETLKW, &cerrojo); 

      waitpid(childpid,&status,0); 
      waitpid(childpid2,&status,0); 
     } 
    } 

    if(!childpid||!childpid2){ /* in child 1 or child 2 */ 

     printf("Soy el hijo %d\n",getpid()); 

     int offset0 = (childpid ? 0 : 1); /* child1 gets 0 and 1, child 2 gets 1 and 0 */ 
     int offset1 = (childpid ? 1 : 0); 
     cerrojo.l_len = 1; 


     cerrojo.l_start = offset0; /* lock door 0 (1) as soon as parent lets us*/ 
     printf("PID %d locking byte %d\n", getpid(), offset0); 
     if(fcntl(fd, F_SETLKW,&cerrojo) == -1){ 
      printf("CERROJO byte %d FALLA EN PID %d (%s)\n",offset0, getpid(), strerror(errno)); 
     } 

     sleep(1); /* guarantee that the other child has our next door locked ... */ 
     printf("PID %d locking byte %d\n", getpid(), offset1); 
     cerrojo.l_start = offset1; /* lock door 1 (0). The second of both children who gets here closes the circle and faces deadlock */ 
     if(fcntl(fd, F_SETLKW,&cerrojo) == -1){ 
      printf("CERROJO byte %d FALLA EN PID: %d (%s)\n", offset1, getpid(), strerror(errno)); 
     } 

     printf("HIJO %d ACABADO (releasing its lock)\n", getpid()); /* Falling off the end of main() will release the lock anyway */ 

    } 
} 

출력 :

[[email protected]] ~ > ./test     
Soy el hijo 29711 
PID 29711 locking byte 1 
Soy el hijo 29712 
PID 29712 locking byte 0 
Tata va a quitar el cerrojo.... 
PID 29711 locking byte 0 
PID 29712 locking byte 1 
CERROJO byte 1 FALLA EN PID: 29712 (Resource deadlock avoided) 
HIJO 29712 ACABADO (releasing its lock) 
HIJO 29711 ACABADO (releasing its lock) 
+0

그건 제가 원했던 것입니다. 대단히 감사합니다. D –