Chinaunix首页 | 论坛 | 博客
  • 博客访问: 408757
  • 博文数量: 119
  • 博客积分: 1470
  • 博客等级: 上尉
  • 技术积分: 1258
  • 用 户 组: 普通用户
  • 注册时间: 2006-02-24 13:50
文章分类

全部博文(119)

文章存档

2018年(6)

2017年(11)

2016年(4)

2013年(8)

2012年(1)

2011年(2)

2010年(4)

2009年(37)

2008年(16)

2006年(30)

我的朋友

分类: LINUX

2006-12-22 14:10:27

#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) |
给主人留下些什么吧!~~