2011-01-21 19 views
1

我不太瞭解下面的代碼。爲什麼會出現溢出,爲什麼使用sem_trywait()?難道我不能通過旋轉while(sem_trywait(&ptr->nempty) == -1 && errno==EAGAIN);來重複檢查信號量嗎?在unp2書中,爲什麼Posix shm例子中有溢出?

感謝, 傑夫

server2.c:

#include  "cliserv2.h" 
int main(int argc, char **argv) 
{ 

     int    fd, index, lastnoverflow, temp; 
     long offset; 
     struct shmstruct  *ptr; 
     char* addr; 
     if (argc != 2) 
       err_quit("usage: server2 <name>"); 

       /* 4create shm, set its size, map it, close descriptor */ 
     shm_unlink(Px_ipc_name(argv[1]));    /* OK if this fails */ 
     addr =Px_ipc_name(argv[1]); 
     fd = Shm_open(addr, O_RDWR | O_CREAT | O_EXCL, FILE_MODE); 
     ptr = Mmap(NULL, sizeof(struct shmstruct), PROT_READ | PROT_WRITE, 
          MAP_SHARED, fd, 0); 
     Ftruncate(fd, sizeof(struct shmstruct)); 
     Close(fd); 

       /* 4initialize the array of offsets */ 
     for (index = 0; index < NMESG; index++) 
       ptr->msgoff[index] = index * MESGSIZE; 

       /* 4initialize the semaphores in shared memory */ 
     Sem_init(&ptr->mutex, 1, 1); 
     Sem_init(&ptr->nempty, 1, NMESG); 
     Sem_init(&ptr->nstored, 1, 0); 
     Sem_init(&ptr->noverflowmutex, 1, 1); 

       /* 4this program is the consumer */ 
     index = 0; 
     lastnoverflow = 0; 
     for (; ;) { 
       Sem_wait(&ptr->nstored); 
       Sem_wait(&ptr->mutex); 
       offset = ptr->msgoff[index]; 
       printf("index = %d: %s\n", index, &ptr->msgdata[offset]); 
       if (++index >= NMESG) 
         index = 0;        /* circular buffer */ 
       Sem_post(&ptr->mutex); 
       Sem_post(&ptr->nempty); 

       Sem_wait(&ptr->noverflowmutex); 
       temp = ptr->noverflow;   /* don't printf while mutex held */ 
       Sem_post(&ptr->noverflowmutex); 
       if (temp != lastnoverflow) { 
         printf("noverflow = %d\n", temp); 
         lastnoverflow = temp; 
       } 
     } 

     exit(0); 
} 

client2.c:

#include  "cliserv2.h" 

int main(int argc, char **argv) 
{ 

     int    fd, i, nloop, nusec; 
     pid_t pid; 
     char mesg[MESGSIZE]; 
     long offset; 
     struct shmstruct  *ptr; 

     if (argc != 4) 
       err_quit("usage: client2 <name> <#loops> <#usec>"); 
     nloop = atoi(argv[2]); 
     nusec = atoi(argv[3]); 

       /* 4open and map shared memory that server must create */ 
     fd = Shm_open(Px_ipc_name(argv[1]), O_RDWR, FILE_MODE); 
     ptr = Mmap(NULL, sizeof(struct shmstruct), PROT_READ | PROT_WRITE, 
          MAP_SHARED, fd, 0); 
     Close(fd); 

     pid = getpid(); 
     for (i = 0; i < nloop; i++) { 
       Sleep_us(nusec); 
       snprintf(mesg, MESGSIZE, "pid %ld: message %d", (long) pid, i); 
       if (sem_trywait(&ptr->nempty) == -1) { 
         if (errno == EAGAIN) { 
           Sem_wait(&ptr->noverflowmutex); 
           ptr->noverflow++; 
           Sem_post(&ptr->noverflowmutex); 
           continue; 
         } else 
           err_sys("sem_trywait error"); 
       } 
       Sem_wait(&ptr->mutex); 
       offset = ptr->msgoff[ptr->nput]; 
       if (++(ptr->nput) >= NMESG) 
         ptr->nput = 0;   /* circular buffer */ 
       Sem_post(&ptr->mutex); 
       strcpy(&ptr->msgdata[offset], mesg); 
       Sem_post(&ptr->nstored); 
     } 
     msync(ptr, sizeof(struct shmstruct), MS_SYNC); 
     munmap(ptr, sizeof(struct shmstruct)); 
     exit(0); 
} 
+0

如果您說出正在學習的章節,它會有所幫助。 – Juliano 2011-01-21 23:21:40

回答

4

在13.6,這本書解釋瞭如何使用溢出計數器:

溢出計數器

的可能性是存在的客戶端 要發送消息,但應採取所有 消息插槽。但是,如果 客戶端實際上是某些 類型的服務器(可能是FTP服務器或HTTP 服務器),則客戶端不希望 等待服務器釋放插槽。 因此,我們將寫入我們的客戶 ,使他們不會阻止,但 增加noverflow計數器,當 發生這種情況。 (...)

所以,原因是客戶端不應該阻止,即使萬一它不能發送消息。就像你所說的那樣,紡紗並不比直接使用sem_wait()更好,本書前面已經介紹過。作者只是演示瞭如何處理不需要阻塞的不同情況。

+0

客戶端的「不需要屏蔽」是關鍵。謝謝大家。 – Jeff 2011-01-22 03:17:42

相關問題