2014-11-09 2 views
1

У меня проблема при тестировании разностной функции ввода-вывода между стандартом C и C POSIX.IO в стандарте C и C POSIX

Я написал две программы, которые читали символ файла символом, переданным в качестве параметра, и отображали каждый символ сразу после его чтения. Эти программы состоят из трех процессов, которые имеют один и тот же дескриптор и действуют одинаково (идентификация каждого процесса отображается с прочитанным символом).

Первая программа будет записана с помощью стандартных функций POSIX (открытые, чтения)

int main(int argc, char **argv){ 
    int fd; /* Descriptor */ 
    char *fic = argv[1]; /* Le nom du fichier */ 
    int end = 0; 

    /* Sémaphore */ 
    struct sembuf operation; 
    int sem_id;  
    sem_id = semget(ftok(fic, 'S'), 1, 0666|IPC_CREAT); 
    semctl(sem_id, 0, SETVAL, 1); 

    if((fd = open(fic, O_RDONLY, 0666))==-1){ 
     perror("open file\n"); 
     } 

    int i = 0; 
    char c; 
    for(i=0; i<3; i++){ 
     if(fork()==0){ 
      /* Lire */ 
      while(end==0){ 
       operation.sem_num = 0; 
       operation.sem_op = -1; 
       semop(sem_id, &operation, 1); 

       if(read(fd, &c, sizeof(char))>0){ 
        printf("[Pid=%d]%c\n", getpid(), c); 
        } 
       else{ 
        end = 1; 
        break; 
        } 

       operation.sem_num = 0; 
       operation.sem_op = 1; 
       semop(sem_id, &operation, 1); 
       sleep(1); 
       } 
      return EXIT_SUCCESS; 
      } 
     else continue; 
     } 

    for(i=0; i<3; i++){ 
     wait(NULL); 
     } 

    close(fd); 
    semctl(sem_id, 0, IPC_RMID, NULL); 
    return EXIT_SUCCESS;  
    } 

Вторая программа будет записана с функциями библиотеки C (FOPEN, fgetc)

int main(int argc, char **argv){ 
    FILE *fd; /* Descriptor */ 
    char *fic = argv[1]; 
    int end = 0; 

    /* Sémaphore */ 
    struct sembuf operation; 
    int sem_id;  
    sem_id = semget(ftok(fic, 'S'), 1, 0666|IPC_CREAT); 
    semctl(sem_id, 0, SETVAL, 1); 

    if((fd = fopen(fic, "r"))==NULL){ 
     perror("open file\n"); 
     } 

    int i = 0; 
    char c; 
    for(i=0; i<3; i++){ 
     if(fork()==0){ 
      while(end==0){ 
       operation.sem_num = 0; 
       operation.sem_op = -1; 
       semop(sem_id, &operation, 1); 

       if((c = fgetc(fd))!=EOF){ 
        printf("[Pid=%d]%c\n", getpid(), c); 
        } 
       else{ 
        end = 1; 
        break; 
        } 

       operation.sem_num = 0; 
       operation.sem_op = 1; 
       semop(sem_id, &operation, 1); 
       sleep(1); 
       } 
      return EXIT_SUCCESS; 
      } 
     else continue; 
     } 

    for(i=0; i<3; i++){ 
     wait(NULL); 
     } 

    fclose(fd); 
    semctl(sem_id, 0, IPC_RMID, NULL); 
    return EXIT_SUCCESS;  
    } 

В случае C POSIX я обнаружил, что 3 процесса работают параллельно с использованием механизма блокировки семафора. Но в случае стандарта C существует только один процесс, который считывает и отображает символ на экране.

Может ли кто-нибудь сказать мне причину этой разницы?

Большое спасибо.

+0

Обратите внимание, что указатели файлов и стандартные потоки ввода-вывода [также являются частью POSIX] (http://pubs.opengroup.org/onlinepubs/009695399/basedefs/stdio.h.html). – pilcrow

ответ

1

Если я правильно понимаю, вы запускаете свои программы и увидеть результат, как это:

$ echo foo > /tmp/input 
$ ./synchronized-read /tmp/input # PIDs differ; the readers "share" the input 
[Pid=124] f 
[Pid=123] o 
[Pid=125] o 
[Pid=123]       # <-- (newline) 

$ ./synchronized-fgetc /tmp/input # PIDs are all the same; one reader reads all 
[Pid=567] f 
[Pid=567] o 
[Pid=567] o 
[Pid=567]       # <-- (newline) 

Причина заключается в том, что read работает непосредственно на файлах, в то время как fgetc работает на буферном стандарт IO потоков.

Итак, в первой программе каждый читатель читает байт в разное время файла напрямую. Во второй программе первый читатель, получающий семафор, читает во всем файле - вы не показывали нам образец ввода, но это соответствует вашему описанию проблемы, то есть другие читатели сразу же сталкиваются с EOF и выходят.

Если вы измените дочернюю логику в каждом на printf("[Pid=%d]EOF\n", getpid()) в конце ввода, вы ее явно увидите.

Смежные вопросы