2012-08-30 2 views
1
#include <stdio.h> 
#include <unistd.h> 
#include <fcntl.h> 
#include <sys/types.h> 
#include <string.h> 
#include <stdlib.h> 
#include <errno.h> 
#define __USE_GNU 
#include <sched.h> 

void init_lock(struct flock *f) 
{ 
    f->l_type = F_WRLCK;  /* write lock set */ 
    f->l_whence = SEEK_SET; 
    f->l_start = 0; 
    f->l_len = 0; 
    f->l_pid = getpid(); 
} 

int lock(int fd, struct flock *f) 
{ 
    init_lock(f); 
    if(fcntl(fd, F_SETLKW, f) == -1) { 
     fprintf(stderr,"fcntl() failed: %s\n", strerror(errno)); 
     return -1; 
    } 
    return 0; 
} 

int unlock(int fd, struct flock *f) 
{ 
f->l_type = F_UNLCK; 
if(fcntl(fd, F_SETLK, f) == -1) { 
    fprintf(stderr, "fcntl() failed: %s\n", strerror(errno)); 
    return -1; 
} 
return 0; 
} 

int file_op(void *arg) 
{ 
char buff[256]; 
int fd = (int) arg, n; 
struct flock my_lock; 

printf("Trying to get lock\n"); 
if(lock(fd, &my_lock) == -1) { /* lock acquired by a thread */ 
    return -1; 
} 

printf("Got lock: %d\n", getpid()); /* I am printing thread id after lock() */ 
printf("Enter string to write in file : "); 
scanf("%s", buff); 

if((n=write(fd, &buff, strlen(buff))) == -1) { 
    fprintf(stderr, "write() failed: %s\n", strerror(errno)); 
} 

if(unlock(fd, &my_lock) == -1) { 
    return -1; 
} 
printf("Lock Released: %d\n", getpid()); 
return 0; 
} 

int main() 
{ 
char *stack; 
int fd, i=0, cid, stacksize; 

if((fd = open("sample.txt", O_CREAT | O_WRONLY | O_APPEND, 0644)) == -1) { 
    printf("Error in file opening\n"); 
    exit(1); 
} 

stacksize = 3*1024*1024; 
for(i=0; i<5; i++) { 
    stack = malloc(stacksize); 
    if((cid = clone(&file_op, stack + stacksize, CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | CLONE_THREAD, (void *) fd)) == -1) { 
     fprintf(stderr,"clone() failed: %s\n", strerror(errno)); 
     break; 
    } 
} 
sleep(30); 
close(fd); 
return 0; 
} 

모든 복제본()이 잠금을 기다리고 싶습니다. 그러나이 코드의 출력 (이 같은) :클론 (2) CLONE_FILES 누출 fcntl 잠금?

Trying to get lock 
Trying to get lock 
Trying to get lock 
Got lock: Got lock: 10287 
Got lock: Got lock: 10287 

Enter string to write in file : Trying to get lock 
Enter string to wriGot lock: 10287 
Got lock: 10287 
Got lock: 10287 
Enter string to write in file : Trying to get lock 
Got lock: 10287 
Got lock: Enter string to write in file : 

하지만 CLONE_FILES에게 클론 (2)에서 필드 설정을 제거하고 할 때, 그것은 잘 간다. 다른 복제 스레드는 잠금()을 기다립니다. 그

출력 : (CLONE_FILES 포함)

Trying to get lock 
Got lock: 10311 
Trying to get lock 
Trying to get lock 
Trying to get lock 
Trying to get lock 

다른 대안? 그리고 왜 이런 종류의 행동?

이 필드의 초보자입니다.

+0

들여 쓰기가 올바른지 확인하십시오. 특히 이처럼 거대한 코드 덤프가있는 경우, 거의 보이지 않는 경우 모든 사람이주의 깊게 읽어야합니다. –

+0

Ohhkk budy. 나는 돌봐 줄 것이다. –

답변

2

flock에 의해 제공되는 잠금은 스레드마다가 아니라 프로세스마다 수행됩니다.

http://linux.die.net/man/2/flock (강조 내)에서 :

통화가 무리()의 호환 잠금 다른 프로세스에 유지된다면 차단된다.

이미 잠긴 파일에 대한 후속 flock() 호출은 기존 잠금을 ​​새 잠금 모드로 변환합니다.

flock()에 의해 생성 된 잠금은 열린 파일 테이블 항목과 연관됩니다.

스레드가 명시 적으로 언급되지는 않았지만 여러 스레드는 파일 테이블 항목을 공유하지만 여러 프로세스는 그렇지 않습니다. CLONE_FILESclone으로 전달하면 '프로세스'가 파일 테이블을 공유하게됩니다.

해결책은 더 많은 파일 설명자를 만들기 위해 dup을 호출하는 것일 수 있습니다. 문서에서 :

공정 (2) (또는 이와 유사한) 동일한
파일의 하나 이상의 디스크립터를 획득하는 오픈 사용하는 경우,이 설명은 독립적으로 무리()을 처리한다. 이러한 파일 설명자 중 하나를 사용하여 파일을 잠그려고하면 호출 프로세스에 이 이미 다른 설명자를 통해있는 잠금에 의해 거부 될 수 있습니다.

+0

동일한 파일에 대해 서로 다른 fds를 사용하지 않는다면 프로세스 내에서 단일 fd를 공유/dup한다는 것은 무리가 작동하지 않는다고 생각하는 것입니다. 나 맞아? –

+0

맞습니다. 그러나 call dup을 사용하여 두 번째 fd를 얻으면 무리가 작동합니다. – jleahy

+0

그러나 공유 fds (CLONE_FILES를 사용하고 자식 스레드에서 dup을 사용하지 않고)를위한 적절한 해결책은 무엇입니까? –