前言:线程如何同步应该知道了吧?不知道也没关系,可以参考我的这篇博客:https://www.cnblogs.com/liudw-0215/p/9685498.html,带你get线程同步。那进程如何同步呢?将介绍两种方式:互斥锁、文件锁,由我娓娓道来。
一、互斥锁
1、介绍
一看到互斥锁,就会想到线程也用这个方法同步,那怎么应用到进程呢?
进程间也可以使用互斥锁,来达到同步的目的。但应在pthread_mutex_init初始化之前,修改其属性为进程间共享。
2、主要函数
pthread_mutexattr_t mattr 类型: 用于定义mutex锁的【属性】
(1)pthread_mutexattr_init函数
初始化一个mutex属性对象
int pthread_mutexattr_init(pthread_mutexattr_t *attr);
(2)pthread_mutexattr_destroy函数
销毁mutex属性对象 (而非销毁锁)
int pthread_mutexattr_destroy(pthread_mutexattr_t *attr);
(3)pthread_mutexattr_setpshared函数
修改mutex属性。
int pthread_mutexattr_setpshared(pthread_mutexattr_t *attr, int pshared);
参2:pshared取值:
线程锁:PTHREAD_PROCESS_PRIVATE (mutex的默认属性即为线程锁,进程间私有)
进程锁:PTHREAD_PROCESS_SHARED
主要就是要用这个pthread_mutexattr_setpshared函数,将属性设置为进程间共享。
3、示例程序
程序如下:
#include <stdio.h> #include <unistd.h> #include <fcntl.h> #include <stdlib.h> #include <string.h> #include <pthread.h> #include <sys/mman.h> #include <sys/wait.h> struct mt { int num; pthread_mutex_t mutex; pthread_mutexattr_t mutexattr; }; int main(void) { int i; struct mt *mm; pid_t pid; /* int fd = open("mt_test", O_CREAT | O_RDWR, 0777); ftruncate(fd, sizeof(*mm)); mm = mmap(NULL, sizeof(*mm), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); close(fd); unlink("mt_test"); */ mm = mmap(NULL, sizeof(*mm), PROT_READ|PROT_WRITE, MAP_SHARED|MAP_ANON, -1, 0); memset(mm, 0, sizeof(*mm)); pthread_mutexattr_init(&mm->mutexattr); //初始化mutex属性对象 pthread_mutexattr_setpshared(&mm->mutexattr, PTHREAD_PROCESS_SHARED); //修改属性为进程间共享 pthread_mutex_init(&mm->mutex, &mm->mutexattr); //初始化一把mutex琐 pid = fork(); if (pid == 0) { for (i = 0; i < 10; i++) { pthread_mutex_lock(&mm->mutex); (mm->num)++; pthread_mutex_unlock(&mm->mutex); printf("-child----------num++ %d ", mm->num); } } else if (pid > 0) { for ( i = 0; i < 10; i++) { // sleep(1); pthread_mutex_lock(&mm->mutex); mm->num += 2; pthread_mutex_unlock(&mm->mutex); printf("-------parent---num+=2 %d ", mm->num); } wait(NULL); } pthread_mutexattr_destroy(&mm->mutexattr); //销毁mutex属性对象 pthread_mutex_destroy(&mm->mutex); //销毁mutex munmap(mm,sizeof(*mm)); //释放映射区 return 0; }
二、文件锁
1、fcntl函数
文件锁的实现主要就是通过fcntl函数来实现的,所以先来介绍这个函数。
功能:借助 fcntl函数来实现锁机制。 操作文件的进程没有获得锁时,可以打开,但无法执行read、write操作。
原型:int fcntl(int fd, int cmd, ... /* arg */ );
参数说明:
参数1:文件描述符
参数2:
F_SETLK (struct flock *) 设置文件锁(相当于trylock,不成功直接返回)
F_SETLKW (struct flock *) 设置文件锁(相当于lock,不成功一直阻塞)W --> wait
F_GETLK (struct flock *) 获取文件锁
struct flock {
...
short l_type; 锁的类型:F_RDLCK 、F_WRLCK 、F_UNLCK
short l_whence; 偏移位置:SEEK_SET、SEEK_CUR、SEEK_END
off_t l_start; 起始偏移:1000
off_t l_len; 长度:0表示整个文件加锁
pid_t l_pid; 持有该锁的进程ID:(F_GETLK only)
...
};
2、示例程序
程序如下:
#include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> #include <stdlib.h> void sys_err(char *str) { perror(str); exit(1); } int main(int argc, char *argv[]) { int fd; struct flock f_lock; if (argc < 2) { printf("./a.out filename "); exit(1); } if ((fd = open(argv[1], O_RDWR)) < 0) sys_err("open"); f_lock.l_type = F_WRLCK; /*选用写琐*/ // f_lock.l_type = F_RDLCK; /*选用读琐*/ f_lock.l_whence = SEEK_SET; f_lock.l_start = 0; f_lock.l_len = 0; /* 0表示整个文件加锁 */ fcntl(fd, F_SETLKW, &f_lock); printf("get flock "); sleep(10); f_lock.l_type = F_UNLCK; fcntl(fd, F_SETLKW, &f_lock); printf("un flock "); close(fd); return 0; }
总结:喜欢的帮忙推荐一下,在此谢过了;欢迎评论,交流与学习