semget,semop and semctl functions

<!-- @page { margin: 2cm } P { margin-bottom: 0.21cm } -->

SEMGET FUNCTION

The prototype of semget is

int semget(key_t key , int nsems , int semflg );

We use semget() to get a semaphore set ID. After we call semget() successfully, it returns a non-negative integer, often called sem_id, which other semaphore functions use to access the semaphore set. On error, it returns -1.

Note that the phrase is "semaphore set". That means it is an array of semaphores, and the 2nd argument nsems decides how many elements the array owns, though almost we just need 1.

I was a little confused by the 1st argument key at first, because I don't know how it works.

Then I looked up the linux manual page.

Here comes the partial description of semget():

The semget() system call returns the semaphore set identifier associated with the argument key. A new set of nsems semaphores is created if key has the value IPC_PRIVATE or if no existing semaphore set is associated with key and IPC_CREAT is specified in semflg.

And then I know the parameter key is an integer associated to the special semaphore. When the system plans to create a new semaphore, it checks the key first to see if another one connected to the key has existed, if so, the system fails with errno.

On another occasion, if we set the key to IPC_PRIVATE, then we can obtain a private semaphore, that means the semaphore can only be accessed by one particular process or thread, so we know it is useless. Always we should provide a unique and non-zero integer for key.



SEMOP FUNCTION

The prototype of semop is

int semop(int semid , struct sembuf * sops , unsigned nsops );

We could easily know that this function is used to perform some operation on semaphores from the name of it.

But how it actually works?

As is refered to above, the function semget() returns an ID pointing to an array of semaphores, and the argument nsems in semget() indicates how many they are. So when we decide to make some change on semaphores, we should know where the semaphores are first, so we get the semid pointing to the array. And then we should know how many operations will be performed, that is why the 3 rd parameter nsops exists.

Finally, how we make changes on the semaphores? We use struct sembuf.

The structure comes below:

unsigned short sem_num; /* semaphore number */

short sem_op; /* semaphore operation */

short sem_flg; /* operation flags */

sem_num indicates which semaphore in the set would be operate, usually it is set to 0.

sem_op holds the value by which the semaphore would change. Generally, +1 is used for P operation and -1 for V to say that the critical section is available now.

It is good to set the sem_flg to SEM_UNDO, so that when the process terminates, the operation could be undone automatically.

On the whole, we use semid to point to the destination set, sops to indicates where the operation array is, then the system performs nsops operation to make changes on the semaphores in the sops array order.

For instance, we call semop(sem_id, buf, 3). The 2nd argument buf is a pointer pointing to an array of struct sembuf owning at least 3 elements. The system catch the 3rd argument 3 to know 3 operations will be performed with the information given by the 2nd argument buf. We said that these operations will be performed in the sops array order, so the system would just make changes on semaphores whose ID is among buf[0].sem_num, buf[1].sem_num and buf[2].sem_num, and of course, each operation will be done according to the buf[i].sem_op, in which i is among 0, 1, 2.

Note that the operation is done atomically and automatically.



SEMCTL FUNCTION

The prototype of the semctl is:

int semctl(int semid , int semnum , int cmd , ...);

This function performs an direct operation on the semnum-th semaphore in the semaphore set whose ID is semid with the argument cmd.

There are many kinds of cmd, which affects the 4th argument's existence.Usually we use two command, SETVAL and IPC_RMID.

For command SETVAL we need a 4th argument to indicate the value to set to the semnum-th semaphore in the set owning the ID semid.

The 4th argument structure follows:

union semun {

int val; /* Value for SETVAL */

struct semid_ds *buf; /* Buffer for IPC_STAT, IPC_SET */

unsigned short *array; /* Array for GETALL, SETALL */

struct seminfo *__buf; /* Buffer for IPC_INFO

(Linux-specific) */

};

And for command IPC_RMID, we aims at removing the semaphore set whose ID is semid, and awakening the processes blocked for the set. Under this circumstance, the argument semnum is ignored.


Jason Lee

2009-11-14 p.m

P.S. 一家之言,如有不足,请多加指正。

你可能感兴趣的:(functions)