利用管道实现进程间同步

    xiaoxiao2021-04-15  37

      进程间同步是指进程的运行有先后顺序,如A进程等待B进程执行完某个动作A进程才能继续往下运行。进程间通信的方法都可以用来同步,只是操作是否方便的一个问题。复习了UNIX高级编程,觉得POSIX的信号量是使用起来最方便的。可是无奈程序写完放到板子里面跑时,打印提示sem_open:function not implemented。坑了。这要改可能要重新编译库,这感觉并不容易,于是决定实现一个类似信号量接口的同步函数。   有名管道有个特性是当以只读方式打开管道时会一直阻塞到有其他地方以写打开的时候。利用这个特性便可以实现进程同步了。  程序最上面实现的一个通用操作,在main里面调用这些接口来进行测试,如下: lock.c

    #include <stdio.h> #include <stdlib.h> #include <string.h> #include <fcntl.h> #include <sys/stat.h> #include <unistd.h> #include <linux/limits.h> /* For PATH_MAX */ struct l_lock { char path[PATH_MAX]; int fd; }; /* 进程间同步的锁操作封装,利用有名管道实现 使用方法: 先用l_open_lock创建锁,path为一个普通路径,flag可以为O_CREAT和O_EXCL的组合 务必判断l_open_lock的返回值。然后用l_lock加锁,l_unlock解锁,最后用 l_close_lock来释放锁资源 风险: 当进程异常退出没有执行l_close_lock删掉管道,那么管道会一直存在,使用O_EXCL标志位 执行l_open_lock会总是失败。 */ struct l_lock *l_open_lock(const char *path, int flag) { if(!path) return NULL; int ret; struct l_lock *lock = NULL; struct stat st; lock = malloc(sizeof(struct l_lock)); if(!lock) { return NULL; } lock->fd = -1; strncpy(lock->path, path, PATH_MAX - 1); ret = stat(path, &st); /* 管道已存在的情况 */ if(ret == 0) { /* 指定O_EXCL标志,那么直接退出 */ if(flag & O_EXCL) { free(lock); return NULL; } else { return lock; } } /* 管道不存在的情况 */ if(flag & O_CREAT) { ret = mkfifo(path, 0666); if(0 != ret) { free(lock); return NULL; } return lock; } else { free(lock); return NULL; } } int l_lock(struct l_lock *lock) { if(!lock && lock->fd != -1) return -1; lock->fd = open(lock->path, O_RDONLY); return 0; } int l_unlock(struct l_lock *lock) { if(!lock && lock->fd != -1) return -1; lock->fd = open(lock->path, O_WRONLY); return 0; } void l_close_lock(struct l_lock *lock) { if(lock) { close(lock->fd); unlink(lock->path); free(lock); } } int main() { struct l_lock *lock = l_open_lock("/tmp/123lock", O_CREAT | O_EXCL); if(!lock) { printf("l open lock failed\n"); return; } printf("wait...\n"); l_lock(lock); printf("wait weakup\n"); l_close_lock(lock); return 0; }

    unlock.c

    #include <stdio.h> #include <stdlib.h> #include <string.h> #include <fcntl.h> #include <sys/stat.h> #include <unistd.h> #include <linux/limits.h> /* For PATH_MAX */ struct l_lock { char path[PATH_MAX]; int fd; }; /* 进程间同步的锁操作封装,利用有名管道实现 使用方法: 先用l_open_lock创建锁,path为一个普通路径,flag可以为O_CREAT和O_EXCL的组合 务必判断l_open_lock的返回值。然后用l_lock加锁,l_unlock解锁,最后用 l_close_lock来释放锁资源 风险: 当进程异常退出没有执行l_close_lock删掉管道,那么管道会一直存在,使用O_EXCL标志位 执行l_open_lock会总是失败。 */ struct l_lock *l_open_lock(const char *path, int flag) { if(!path) return NULL; int ret; struct l_lock *lock = NULL; struct stat st; lock = malloc(sizeof(struct l_lock)); if(!lock) { return NULL; } lock->fd = -1; strncpy(lock->path, path, PATH_MAX - 1); ret = stat(path, &st); /* 管道已存在的情况 */ if(ret == 0) { /* 指定O_EXCL标志,那么直接退出 */ if(flag & O_EXCL) { free(lock); return NULL; } else { return lock; } } /* 管道不存在的情况 */ if(flag & O_CREAT) { ret = mkfifo(path, 0666); if(0 != ret) { free(lock); return NULL; } return lock; } else { free(lock); return NULL; } } int l_lock(struct l_lock *lock) { if(!lock && lock->fd != -1) return -1; lock->fd = open(lock->path, O_RDONLY); return 0; } int l_unlock(struct l_lock *lock) { if(!lock && lock->fd != -1) return -1; lock->fd = open(lock->path, O_WRONLY); return 0; } void l_close_lock(struct l_lock *lock) { if(lock) { close(lock->fd); unlink(lock->path); free(lock); } } int main() { struct l_lock *lock = l_open_lock("/tmp/123lock", 0); if(!lock) { printf("l open lock failed"); return; } l_unlock(lock); printf("please weakup\n"); l_close_lock(lock); return 0; }

    执行效果:执行lock程序后,程序会阻塞,直到执行unlock的程序将其唤醒为止。

    root@ubuntu:AC_PRODUCT_SVN5449# ./lock & [1] 13602 root@ubuntu:AC_PRODUCT_SVN5449# wait... root@ubuntu:AC_PRODUCT_SVN5449# ./unlock wait weakup please weakup [1]+ Done ./lock
    转载请注明原文地址: https://ju.6miu.com/read-671542.html

    最新回复(0)