2014-11-26 5 views
1

Я тестирую, если блокировка файлового дескриптора из другого потока затронет основной поток.Какова область действия flock()?

#include <iostream> 
#include <stdlib.h> 
#include <unistd.h> 
#include <fcntl.h> 
#include <sys/stat.h> 
#include <sys/types.h> 
//#include <share.h> 
#include <stdio.h> 
#include <pthread.h> 
#include <errno.h> 

void *print_message_function(void *ptr); 

pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER; 

int main (int argc, char * const argv[]) { 

    pthread_t thread1, thread2; 
const char *message1 = "Thread 1"; 
const char *message2 = "Thread 2"; 
int iret1, iret2; 

    iret2 = pthread_create(&thread2, NULL, print_message_function, (void*) message1); 

    if(iret2) 
    { 
     fprintf(stderr,"Error - pthread_create() return code: %d\n",iret2); 
     fflush(stdout); 
     exit(EXIT_FAILURE); 
    } 

     printf("pthread_create() for thread 2 returns: %d\n",iret2); 

    pthread_mutex_lock(&mut); 
    sleep(1); 

    std::cout<<"Enter any key:"<<std::endl; 
    std::cin >> input; 

    if (fd2 = open("file1", O_RDWR | O_CREAT | O_TRUNC, 0700 | 0x10) == -1) 
    { 
     perror("Cannot open file 2.\n"); 
     fflush(stdout); 
    } 
    else 
    { 
     printf("File was opened 2!!\n"); 
     fflush(stdout); 
     if(flock(fd2, LOCK_NB | LOCK_EX)==0) 
     { 
      printf("THE FILE WAS LOCKED 2.\n"); 
     } 
     else if(errno == EAGAIN) 
     { 
      printf("The file is locked 2. Resource temporarily unavailable.\n"); 
     } 
    } 

    pthread_mutex_unlock(&mut); 

    close(fd2); 
    std::cout<<"File closed."<<std::endl; 
    std::cin >> input; 
    return 0; 
} 


void *print_message_function(void *ptr) 
{ 
    char *message; 
    message = (char *) ptr; 
    printf("%s \n", message); 
    fflush(stdout); 

    int fd1; 

    if ((fd1 = open("file1", O_RDWR | O_CREAT | O_TRUNC, 0700 | 0x10)) == -1) 
    { 
     perror("thread: Cannot open file 1.\n"); 
     fflush(stdout); 
     //std::cin >> input; 
    } 
    else 
    { 
     printf("File was opened 1!!\n"); 
     fflush(stdout); 


     if(flock(fd1, LOCK_NB | LOCK_EX)==0) 
     { 
      printf("THE FILE WAS LOCKED 1.\n"); 
     } 
     else if(errno == EAGAIN) 
     { 
      printf("The file is locked 1. Resource temporarily unavailable.\n"); 
     } 
    } 

    pthread_mutex_lock(&mut); 
    pthread_mutex_unlock(&mut); 

    printf("End of thread.\n"); 
} 

Выход:

[Session started at 2014-11-26 17:46:16 +0000.] 
pthread_create() for thread 2 returns: 0 
Thread 1 
File was opened 1!! 
THE FILE WAS LOCKED 1. 
Enter any key: 
1 
File was opened 2!! 
THE FILE WAS LOCKED 2. 
File closed. 
End of thread. 

Я не понимаю, почему стая() используется внутри нити не мешает паствы() используется в основном потоке получать блокировку.

От человека странице Linux:

Блокировки, созданные паствы() связаны с открытым описанием файла (см открыт (2)). Это означает, что дубликаты файловых дескрипторов (созданных , например, fork (2) или dup (2)) относятся к одной и той же блокировке, и этот замок может быть изменен или выпущен с использованием любого из этих дескрипторов. Кроме того, блокировка освобождается либо явной операцией LOCK_UN на любом из этих дублирующих дескрипторов, либо когда все такие дескрипторы были закрыты.

+0

возможно дубликат [несколько потоков, способных получить паству в то же время] (http://stackoverflow.com/questions/9462532/multiple-threads-able-to-get-flock -та-то же самое время) – pilcrow

+0

@pilcrow, а не обман. В вопросе, на который вы ссылаетесь, различные потоки используют один и тот же файловый дескриптор (или, если нет, то ни один из ответов не является удовлетворительным). В этом случае они открывают отдельные дескрипторы в одном файле. В документах 'flock()' s на разных дескрипторах, открытых в одном файле, действительно блокируют друг друга. –

+0

Немного странно, что 'print_message_function()' блокирует и разблокирует мьютекс в конце, но не выполняет какую-либо свою работу в рамках мьютекса. Является ли поведение отличным, если вы выполняете хотя бы 'flock()', удерживая мьютекс (как это уже делает другой поток)? Примечание: вам нужно переместить «sleep()» основного потока из его критического раздела. –

ответ

4

Typo. Эта линия неправильно устанавливает fd2 (который вы не объявляли в вашей публикуемой коде, кстати) до 0, а именно, stdin:.

if (fd2 = open("file1", O_RDWR | O_CREAT | O_TRUNC, 0700 | 0x10) == -1) 

Таким образом, fd1 и fd2 почти наверняка относятся к разным файлам и точкам ваше упражнение потеряно. Вы хотите сказать:

if ((fd2 = open("file1", ...)) == -1) 
Смежные вопросы