#include
#include
#include
#include
#include
#include
#include
#include
#include
#if defined(__GNU_LIBRARY__) && !defined(_SEM_SEMUN_UNDEFINED)
/* union semun is defined by including */
#else
/* according to X/OPEN we have to define it ourselves */
union semun {
int val; /* value for SETVAL */
struct semid_ds *buf; /* buffer for IPC_STAT, IPC_SET */
unsigned short *array; /* array for GETALL, SETALL */
/* Linux specific part: */
struct seminfo *__buf; /* buffer for IPC_INFO */
};
#endif
#define SEM_KEY "."
#define SEM_MODE1 00666|IPC_CREAT|IPC_EXCL
#define SEM_MODE2 00666|IPC_CREAT
#define SEM_NUM 10
extern int errno;
int semid;
int init_sem(int sid, int max_tries)
{
struct semid_ds sem_info;
union semun sem_arg;
int i, init_ok = 0;
for (i = 0; i< max_tries; i++)
{
sem_arg.buf = &sem_info;
if (semctl(sid, 0, IPC_STAT, sem_arg) == -1)
{
perror("semctl error");
return -1;
}
else
{
if(sem_arg.buf->sem_otime != 0)
{
init_ok = 1;
i = max_tries;
}
else sleep(1);
}
}
if (!init_ok)
{
sem_arg.val = SEM_NUM;
if(semctl(sid, 0, SETVAL, sem_arg)==-1)
{
perror("semctl setval");
return -1;
}
}
return 0;
}
int wait_sem(int sid) // P operation
{
struct sembuf op = {0, -1, SEM_UNDO};
int ret;
while((ret = semop(sid, &op, 1)) < 0 && errno == EINTR);
if (ret < 0)
{
perror("wait_sem");
return -1;
}
return 0;
}
int free_sem(int sid) // V operation
{
struct sembuf op = {0, 1, SEM_UNDO};
int ret;
while((ret = semop(sid, &op, 1)) < 0 && errno == EINTR);
if (ret < 0)
{
perror("free_sem");
return -1;
}
return 0;
}
int remove_sem(int sid)
{
if(semctl(sid, 0, IPC_RMID)==-1)
{
perror("remove_sem");
return -1;
}
return 0;
}
void wait_child(int sig)
{
int ret;
while(1)
{
while ((ret = waitpid(-1, NULL, WNOHANG)) > 0)
{
free_sem(semid);
}
if (ret < 0 && errno == EINTR)
{
continue;
}
else
{
break;
}
}
}
void abort_parent(int sig)
{
if (remove_sem(semid) < 0)
{
printf("semaphore %d removed successfully\n", semid);
}
exit(0);
}
int get_sem(key_t key, int* is_new)
{
int semid;
semid = semget(key, 1, SEM_MODE1);
if (semid < 0)
{
if (errno != EEXIST)
{
perror("get_sem:creat");
return -1;
}
semid = semget(key, 0, SEM_MODE2);
if (semid < 0)
{
perror("get_sem:get");
return -1;
}
if (is_new) *is_new = 0;
}
else if (is_new)
{
*is_new = 1;
}
return semid;
}
int main(void)
{
key_t key;
pid_t pid;
unsigned long tick;
int status;
key= ftok(".", 'a');
if (key == -1) {
perror("ftok");
exit(1);
}
semid = get_sem(key, &status);
if (semid < 0)
{
printf("failed to get semaphore.\n");
exit(1);
}
if (status == 1) status = init_sem(semid, 0); // is a new semaphore
else
{
printf("semaphore %d already existing", semid);
exit(0);
}
if (status < 0)
{
printf("failed to init semahpore.\n");
exit(1);
}
signal(SIGCHLD, wait_child);
signal(SIGINT, abort_parent);
tick = 0;
while(1)
{
fprintf(stderr, "%s\n", "test");
if (wait_sem(semid) == -1)
{
printf("error when waiting semphore free.\n");
remove_sem(semid);
exit(0);
}
tick++;
pid = fork();
if (pid < 0)
{
remove_sem(semid);
printf("process forking abnormally.\n");
exit(1);
}
else if (pid == 0) // child process
{
signal(SIGINT, SIG_DFL);
printf("I am child %ld\n", tick);
sleep(1);
printf("child %ld exiting\n", tick);
exit(0);
//break;
}
fprintf(stderr, "%s\n", "dddddddddddd");
}
return(0);
}
阅读(1112) | 评论(0) | 转发(0) |