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);
  }
  



Paweł Niewiadomski
2000-10-17