Beispiel #1
0
int create_sema(int key, int val) {
    int semid;
    struct sembuf sem_tmp;
    semid = semget(key, 1, 0777|IPC_CREAT|IPC_EXCL);
    if(semid == -1) {
        perror("create_sema: ");
        if (errno == EEXIST) {
            semid = semget(key, 1, 0777);
            if (semctl(semid, 0, IPC_RMID) >= 0) {
                semid = semget(key, 1, 0777|IPC_CREAT|IPC_EXCL);
                if (semid == -1) {
                    perror("create_sema: semget: ");
                    return FALSE;
                }
            } else {
                perror("create_sema: semaphore exists and can't be removed: ");
                return FALSE;
            }
        } else {
            perror("create_sema: ");
            return FALSE;
        }
    }
    set_sembuf_struct(&sem_tmp, 0, val, 0);
    semop(semid, &sem_tmp, 1);
    return TRUE;
}
Beispiel #2
0
int main(int argc, char *argv[]) 
{ 
	pid_t pid, ppid, childpid, w;                 		 // For process ID, parent process ID, child process, and wait
	pid_t leader = getpid();							 // Used to make sure the child process finishes before the parent is killed
	int semid, semop_ret, sem_value, i, j, opt;			 // Semaphore ID, Semaphore value, i and j for for statement, and Semaphore option
	int N, status, k;									 // Number of processes, the status for wait, and the delay paramater
	char buf_num[MAX_CANON], *c_ptr;					 // Character buffer and pointer to navigate it
	key_t ipc_key; 										 // Key for Semaphore
	struct semid_ds sem_buf;							 // Allows access for Semaphore set and reference to the array of type sem 	

	/* Check input arguments are 4 */
	if (argc != 4)
	{
		printf("Invalid input.  The number of arguments must be 4.\n");
		exit(1);
	}
	/* Make sure number of precesses is more than 0 */
	if(atoi(argv[1]) > 0)
	{
		N = atoi(argv[1]);
	}
	else
	{
		printf("Invalid input. %d(N) must be greater then 0.\n", atoi(argv[1]));
		exit(1);
	}

	/* Declare the operation for semaphore protection */
	if (strcmp(argv[2], "n") == 0) /* No semaphore protection */		
	{
		opt = 0;
	}
	else if (strcmp(argv[2], "s") == 0) /* Semaphore protection */
 	{
 		opt = 1;
 	}
 	else
	{
		printf("Invalid input for the second argument. %s should be 'n' or 's'.\n", argv[1]);
		exit(1);
	}

	/* Initialize the delay parameter, 'k', if it is greater than 0 */
	if(atoi(argv[3]) > 0)
		k = atoi(argv[3]);
	else
	{
		printf("Invalid input. %d(k) must be greater then 0.\n", atoi(argv[3]));
		exit(1);
	}

	/* Decalre semaphore wait and increment */
	struct sembuf semwait[1]; 
 	struct sembuf semsignal[1];

 	/* Initialize semaphore element to 1 */ 
 	set_sembuf_struct(semwait, 0, -1, 0); 
 	set_sembuf_struct(semsignal, 0, 1, 0); 

	ipc_key = ftok(".", 'S'); 			// Generate a key from a pathname
	
	/* Create semaphore */
	/* A semaphore is always created reguardless of semaphore procetion. It is only used if k = s */ 
	if ((semid = semget(ipc_key, 1, IPC_CREAT | IPC_EXCL | 0666)) == -1) 
	{
        perror ("semget: IPC | 0666");
        exit(1);
	}

	/* Attempt to increment the semaphore */
	if(semop(semid, semsignal, 1) == -1) 
	{
	    printf("%ld: semaphore increment failed - %s\n", (long)getpid(), strerror(errno)); 
	    /* Remove the semaphore if unable to increment */
	        if (semctl(semid, 0, IPC_RMID) == -1) 
	            printf ("%ld: could not delete semaphore - %s\n", (long)getpid(), strerror(errno)); 
	            exit(1); 
	}
	
	/* Create the processes based on the value of 'N' */
	childpid = 0;
	for(i = 1; i < N; i++)
	{
		if(childpid = fork()) break; 
	}

	/* If semaphore protection is used, decrement the semaphore and enter it */
	if(opt)
	{
		while (( (semop_ret = semop(semid, semwait, 1) ) == -1) && (errno ==EINTR)); 
		    if (semop_ret == -1) 
		        printf ("%ld: semaphore decrement failed - %s\n", (long)getpid(), strerror(errno)); 
	}

	/* Create the output message and put in into a character buffer */
	sprintf(buf_num,"i: %d: process ID: %6ld parent ID: %6ld child ID: %6ld\n",i,(long)getpid(), (long)getppid(), (long)childpid);

	/* Direct the pointer to the char buffer */ 
	c_ptr = buf_num;

	/* Specifies the buffer to be used by the stream for I/O operations, which becomes a    */
	/* fully buffered stream. Or, alternatively, if buffer is a null pointer, buffering is  */
	/* disabled for the stream, which becomes an unbuffered stream. 						*/
	setbuf(stdout, NULL);

	/* Cycle through the char buffer using the pointer until it points to NULL */
	while (*c_ptr != '\0')
	{
		fputc(*c_ptr, stderr);
		/* Sleep in usec microsecond using the delay adjustment parameter */
		usleep(k);
		c_ptr++;
	}

	/* If semaphor protection is enabled, increment the semaphore */ 
	if(opt)
	{
		while ( ( (semop_ret = semop(semid, semsignal, 1) ) == -1) && (errno == EINTR) ); 
			if (semop_ret == -1) 
			    printf ("%ld: semaphore increment failed - %s\n", (long)getpid(), strerror(errno));
	}

	/* Wait for the child process to complete before the parent is killed */
	waitpid(childpid, &status, 0);

	/* Once the process has completed, remove the semaphore */
	if(leader == getpid())
	{
        if(semctl(semid, 0, IPC_RMID) == -1)
        {
            printf("%ld: couldn't delete semaphore - %s\n", (long)getpid(), strerror(errno));
            exit(1);
        }
    }
  exit(0);
}