Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/56.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/unix/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 为什么不';当几个进程用F_SETLKW锁定同一个fd时,我看到死锁(EDEADLK)了吗?_C_Unix_Deadlock_Fcntl - Fatal编程技术网

C 为什么不';当几个进程用F_SETLKW锁定同一个fd时,我看到死锁(EDEADLK)了吗?

C 为什么不';当几个进程用F_SETLKW锁定同一个fd时,我看到死锁(EDEADLK)了吗?,c,unix,deadlock,fcntl,C,Unix,Deadlock,Fcntl,我需要妥善处理EDEADLK。在我的程序中,我看到两个孩子都等到父母睡觉,然后他们应用锁,然后马上离开。对不起我的错误,我是一名西班牙学生 int main(){ pid_t childpid, childpid2; struct flock cerrojo; int fd, status; if ((fd=open("prueba", O_RDWR)) == -1) perror("apertura fallo"); cerro

我需要妥善处理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;

}

对于死锁,您至少需要两个锁。我总是想象自己被锁在A房间,带着B房间的钥匙,而另一个人被锁在B房间,带着A房间的钥匙

在您的示例中,只有一个锁:两个孩子都试图锁定同一个大“门”(整个文件)。第二个到达那里的人将阻塞,直到第一个再次释放锁,然后唱同一首轻快的歌曲锁,睡眠,。。。解锁。看不到僵局

现在,在下面的示例中,父级锁定两个“门”-文件
fd
的第一个和第二个字节指向(顺便说一句,对于您的示例来说这真的是必要的吗?),然后生成两个子级。两个孩子都试图锁定这两个字节,但每个字节都以不同的字节开始。一旦父级释放两个字节,子级就会获得它们的锁,总共尝试了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 */

    }
}

“那个错误”:哪个错误?你预计会发生什么?会发生什么?您是否尝试跟踪该程序(
strace-f
)?你看到了什么?我需要让edeadlk看看内核是如何避免死锁的——至少让我们知道发生了什么,这与你的期望有什么不同。在linux中,strace-r-f-etrace=fcntl将提供大量信息,但即使只是程序的输出也会有所帮助:-)这正是我想要的。非常感谢:D
[hlub@karpaten] ~ > ./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)