一、互斥量 mutex
进程间也可以使用互斥锁 ,来达到同步的目的。但应在 pthread_mutex_init 初始化之前,修改其属性为进程间共享。mutex 的属性修改函数主要有以下几个。
主要应用函数:
1、pthread_mutexattr_t mutexattr 类型: 用于定义互斥锁的属性。
2、pthread_mutexattr_init 函数: 初始化一个 mutex 属性对象
int pthread_mutexattr_init(pthread_mutexattr_t *attr);
3、pthread_mutexattr_destroy 函数: 销毁 mutex 属性对象(而非销毁锁)
int pthread_mutexattr_destroy(pthread_mutexattr_t *attr);
4、pthread_mutexattr_setpshared 函数: 修改 mutex 属性
int pthread_mutexattr_setpshared(pthread_mutexattr_t *attr,int pshared);
参数 2 :pshared 取值:
线程锁: PTHREAD_PROCESS_PRIVATE( mutex 的默认属性即为线程锁,进程间私有)
进程锁:PTHREAD_PROCESS_SHARED
5、进程间互斥量操作代码示例:
/*
互斥量 实现 多进程 之间的同步
*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
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);
if( fd == -1 )
{
perror("open file:");
exit(1);
}
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);
// printf("-------before memset------\n");
memset(mm,0x00,sizeof(*mm));
// printf("-------after memset------\n");
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)++;
printf("-child--------------num++ %d\n",mm->num);
pthread_mutex_unlock(&mm->mutex);
sleep(1);
}
}
else
{
for( i=0;i<10;i++)
{
sleep(1);
pthread_mutex_lock(&mm->mutex);
mm->num += 2;
printf("--------parent------num+=2 %d\n",mm->num);
pthread_mutex_unlock(&mm->mutex);
}
wait(NULL);
}
pthread_mutexattr_destroy(&mm->mutexattr); // 销毁 mutex 属性对象
pthread_mutex_destroy(&mm->mutex); // 销毁 mutex 锁
return 0;
}
二、文件锁
借助 fcntl 函数来实现文件锁。操作文件的进程没有获得锁时,可以打开,但无法执行 read,write 操作。
fcntl 函数:获取、设置文件访问控制属性。
#include
#include
int fcntl(int fd, int cmd, ... /* arg */ );
参数 2 :
F_SETLK(struct flock *); 设置文件锁 ( trylock )
F_SETLKW(struct flock*); 设置文件锁( lock ) W --- wait
F_GETLK(struct flock*); 获取文件锁
参数 3 :
struct flock {
...
short l_type; /* Type of lock: F_RDLCK,
F_WRLCK, F_UNLCK */
short l_whence; /* How to interpret l_start:
SEEK_SET, SEEK_CUR, SEEK_END */
off_t l_start; /* Starting offset for lock */
off_t l_len; /* Number of bytes to lock */
pid_t l_pid; /* PID of process blocking our lock
(F_GETLK only) */
...
};
进程间文件锁 代码示例:
#include
#include
#include
#include
#include
#include
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\n");
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 = 0;
f_lock.l_len = 0; // 0 表示整个文件加锁
fcntl(fd,F_SETLKW,&f_lock);
printf("get flock\n");
sleep(10);
f_lock.l_type = F_UNLCK;
fcntl(fd,F_SETLKW,&f_lock);
printf("un flock\n");
close(fd);
return 0;
}