704486377 发表于 2014-10-10 15:24

关于LINUX 信号量 与 usleep 引发重复上锁的问题求教

在研究学习信号量的时候,发现了一个奇怪了问题,如果在信号量的处理过程中调用usleep睡眠等待,那么会出现,进程A上锁后,进程B也可以上锁(在进程A没有解锁的条件下),但是如果去掉了usleep,是可以正常运行的。代码如下求大神指导,谢谢!!!

#include <basefun.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>

#define SEM_KEY 8999
#define SVSEM_MODE 0644

union semun {
        int val;
        struct semid_ds *buf;
        unsigned short *array;
        struct seminfo *__buf;
};

int sem_init();
int sem_lock(int semid);
int sem_unlock(int semid);
int sem_delete(int semid);
int sem_deal(int semid);
int sem_count(int semid);

void test_wait(int loop);

int main()
{
        int rs, semid;
       
        semid = sem_init();
        _CHECK_RS(semid, -1, -1);

        if (0 == fork()) {
                rs = sem_deal(semid);
                _CHECK_RS(rs, -1, -1);
                return 0;
        }
       
        rs = sem_deal(semid);
        _CHECK_RS(rs, -1, -1);

        GET_INPUT;
        sem_delete(semid);

        return 0;
}

int sem_init() {

        int rs, semid;
        int flag = IPC_CREAT | IPC_EXCL | SVSEM_MODE;
        sembuf sb;

        semid = semget(SEM_KEY, 1, flag);
        _CHECK_RS(semid, -1, -1);
       
        memset(&sb, 0, sizeof(sb));
        sb.sem_num = 0;
        sb.sem_op = 1;
        sb.sem_flg = SEM_UNDO;

        rs = semop(semid, &sb, 1);
        _CHECK_RS(rs, -1, 1);

        return semid;
}

int sem_delete(int semid) {

        int rs;
        rs = semctl(semid, 0, IPC_RMID, NULL);
        _CHECK_RS(rs, -1, -1);
        return 0;
}

int sem_lock(int semid) {

        int rs;
        sembuf sb;

        memset(&sb, 0, sizeof(sb));

        sb.sem_num = 0;
        sb.sem_op = -1;
        sb.sem_flg = SEM_UNDO;

        rs = semop(semid, &sb, 1);
        _CHECK_RS(rs, -1, -1);

        return 0;
}

int sem_unlock(int semid) {

        int rs;
        sembuf sb;

        memset(&sb, 0, sizeof(sb));

        sb.sem_num = 0;
        sb.sem_op = 1;
        sb.sem_flg = SEM_UNDO;

        rs = semop(semid, &sb, 1);
        _CHECK_RS(rs, -1, -1);

        return 0;
}

int sem_deal(int semid) {

        int i, rs;
        struct timespec stime = {0, 100};
       
        for (i = 0; i < 5; i++) {

                rs = sem_lock(semid);       
                _CHECK_RS(rs, -1, -1);
                P("[%ld] lock succeed, count[%d] ...\n", getpid(), sem_count(semid));

                rs = sem_unlock(semid);
                _CHECK_RS(rs, -1, -1);       
                P("[%ld] unlock succeed, count[%d] ...\n", getpid(), sem_count(semid));

                usleep(100);
        }

        return 0;
}

int sem_count(int semid) {

        union semun arg;
        struct semid_ds seminfo;
        arg.buf = &seminfo;

        return semctl(semid, 0, GETVAL, arg);
}

void test_wait(int loop) {

        for (int i = 0; i < loop; i++)
                ;
}

mymtom_cu 发表于 2014-10-16 13:39

楼主上锁后马上就解锁了,usleep 是在sem_unlock之后做的啊,
页: [1]
查看完整版本: 关于LINUX 信号量 与 usleep 引发重复上锁的问题求教