next up previous contents
Next: semstat: kompan programu semtool Up: semtool: interaktywny manipulator semaforów Previous: Przykłady   Contents

Źródło


   /*****************************************************************************
    Zaczerpnięto z "Linux Programmer's Guide - Rozdział 6"
    (C)opyright 1994-1995, Scott Burkett
    ***************************************************************************** 
    MODUŁ: semtool.c
    *****************************************************************************
    Narzędzie zarządzające semaforami stylu SysV z linii poleceń
    *****************************************************************************/
   
   #include <stdio.h>
   #include <ctype.h>
   #include <stdlib.h>
   #include <sys/types.h>
   #include <sys/ipc.h>
   #include <sys/sem.h>
   
   /* U mnie ( RedHat6.0, jądro 2.2.12-20 )
   #include <sys/types.h>
   #include <sys/ipc.h>
   #include <sys/sem.h>	*/
   
   
   #define SEM_RESOURCE_MAX        1       /* wartość inicjująca wszystkie semafory */
   
   void opensem(int *sid, key_t key);
   void createsem(int *sid, key_t key, int members);
   void locksem(int sid, int member);
   void unlocksem(int sid, int member);
   void removesem(int sid);
   unsigned short get_member_count(int sid);
   int getval(int sid, int member);
   void dispval(int sid, int member);
   void changemode(int sid, char *mode);
   void usage(void);
   
   int main(int argc, char *argv[])
   {
           key_t key;
           int   semset_id;
   
           if(argc == 1)
                   usage();
   
           /* tworzymy unikalny klucz za pomocą wywołania ftok() */
           key = ftok(".", 's');
   
           switch(tolower(argv[1][0]))
           {
                   case 's': if(argc != 3)
                                   usage();
                             createsem(&semset_id, key,  atoi(argv[2]));
                             break;
                   case 'z': if(argc != 3)
                                   usage();
                             opensem(&semset_id, key);
                             locksem(semset_id, atoi(argv[2]));
                             break;
                   case 'o': if(argc != 3)
                                   usage();
                             opensem(&semset_id, key);
                             unlocksem(semset_id, atoi(argv[2]));
                             break;
                   case 'u': opensem(&semset_id, key);
                             removesem(semset_id);
                             break;        
                   case 't': opensem(&semset_id, key);
                             changemode(semset_id, argv[2]);
                             break;        
                    default: usage();
   
           }
           
           return(0);
   }
   
   void opensem(int *sid, key_t key)
   {
           /* otwórz zestaw semaforów, nie twórz go! */
   
           if((*sid = semget(key, 0, 0666)) == -1) 
           {
                   printf("Zestaw semaforów nie istnieje!\n");
                   exit(1);
           }
   
   }
   
   void createsem(int *sid, key_t key, int members)
   {
           int cntr;
           union semun semopts;
   
           if(members > SEMMSL) {
                   printf("Przykro mi, maxymalną liczbą semaforów w zestawie jest %d\n",
   SEMMSL);
                   exit(1);
           }
   
           printf("Próbuję utworzyć nowy zestaw semaforów z %d elementami\n",
   members);
   
           if((*sid = semget(key, members, IPC_CREAT|IPC_EXCL|0666))
                           == -1) 
           {
                   fprintf(stderr, "Zestaw semaforów istnieje!\n");
                   exit(1);
           }
   
           semopts.val = SEM_RESOURCE_MAX;
           
           /* Inicjalizacja wszystkich członków ( można to zrobić za pomocą SETALL ) */
           for(cntr=0; cntr<members; cntr++)
                   semctl(*sid, cntr, SETVAL, semopts);
   }
   
   void locksem(int sid, int member)
   {
           struct sembuf sem_lock={ 0, -1, IPC_NOWAIT};
   
           if( member<0 || member>(get_member_count(sid)-1))
           {
                   fprintf(stderr, "%d - członek semaforu poza zasięgiem\n", member);
   return;
           }
   
           /* Próba zablokowania zestawu semaforów */
           if(!getval(sid, member))
           {
                   fprintf(stderr, "Zasoby semaforu wyczerpane ( brak blokady )!\n");
                   exit(1);
           }
           
           sem_lock.sem_num = member;
           
           if((semop(sid, &sem_lock, 1)) == -1)
           {
                   fprintf(stderr, "Blokowanie nie powiodło się\n");
                   exit(1);
           }
           else
                   printf("Zasoby semaforu zmiejszone o jeden ( zablokowane )\n");
   
           dispval(sid, member);
   }
   
   void unlocksem(int sid, int member)
   {
           struct sembuf sem_unlock={ member, 1, IPC_NOWAIT};
           int semval;
   
           if( member<0 || member>(get_member_count(sid)-1))
           {
                   fprintf(stderr, "%d - członek semaforu poza zasięgiem\n", member);
   return;
           }
   
           /* Czy semafor jest zablokowany? */
           semval = getval(sid, member);
           if(semval == SEM_RESOURCE_MAX) {
                   fprintf(stderr, "Semafor nie jest zablokowany!\n");
                   exit(1);
           }
   
           sem_unlock.sem_num = member;
   
           /* Próba odblokowania semaforu */
           if((semop(sid, &sem_unlock, 1)) == -1)
           {
                   fprintf(stderr, "Odblokowywanie nie powiodło się\n");
                   exit(1);
           }
           else
                   printf("Zasoby semaforu zwiększone o jeden ( odblokowane )\n");
   
           dispval(sid, member);
   }
   
   void removesem(int sid)
   {
           semctl(sid, 0, IPC_RMID, 0);
           printf("Usunięto zestaw semaforów\n");
   }
   
   unsigned short get_member_count(int sid)
   {
           union semun semopts;
           struct semid_ds mysemds;
   
           semopts.buf = &mysemds;
   	
   	semctl(sid, 0, IPC_STAT, semopts);
           
   	/* zwraca liczbę członków zestawu semaforów */
           return(semopts.buf->sem_nsems);
   }
   
   int getval(int sid, int member)
   {
           int semval;
   
           semval = semctl(sid, member, GETVAL, 0);
           return(semval);
   }
   
   void changemode(int sid, char *mode)
   {
           int rc;
           union semun semopts;
           struct semid_ds mysemds;
   
           /* pobierz aktalną wartość wewnętrznej struktury */
           semopts.buf = &mysemds;
   
           rc = semctl(sid, 0, IPC_STAT, semopts);
   
           if (rc == -1) {
                   perror("semctl");
                   exit(1);
           }
                   
           printf("Stare prawa dostępu: %o\n", semopts.buf->sem_perm.mode);
   
           /* Zmień prawa dostępu do zestawu semaforów */
           sscanf(mode, "%ho", &semopts.buf->sem_perm.mode);
   
           /* Zaktualizuj wewnętrzną strukturę danych */
           semctl(sid, 0, IPC_SET, semopts);
   
           printf("Zaktualizowano...\n");
   
   }
   
   void dispval(int sid, int member)
   {
           int semval;
   
           semval = semctl(sid, member, GETVAL, 0);
           printf("semval elementu %d to %d\n", member, semval);
   }
   
   void usage(void)
   {
           fprintf(stderr, "semtool - narzędzie do majstrowania przy semaforach\n");
           fprintf(stderr, "\nUŻYCIE:  semtool (s)twórz <ilość semaforów>\n");
           fprintf(stderr, "                 (z)ablokuj <nr sem.>\n");
           fprintf(stderr, "                 (o)dblokuj <nr sem.>\n");
           fprintf(stderr, "                 (u)suń\n");
           fprintf(stderr, "                 (t)ryb <tryb>\n");
           exit(1);
   }
   




2000-03-01


Poltronic