进程间互斥
来源:互联网 发布:php 接口文档管理系统 编辑:程序博客网 时间:2024/05/21 15:51
简单做一下进程间互斥的实现方法,如有不足或错误之处还望各位道友指正!
一、信号量
信号量简单的来说就是一个计数器,当一个进程尝试去读取一个共享资源之前,进程先测试相应的信号量,若信号量大于0,则该进程可以使用共享资源并且将信号量减去sem_op(使用完后将信号量加sem_op),若信号量等于0,则进程进入休眠,等待信号量大于0(即其他进程使用完该资源),以此实现多进程对共享资源的同步访问。
在linux中,信号量实现的函数:
int semget(key_t key, int nsems, int flag);
int semctl(int semid, int semnum, int cmd, /* union semun arg*/);
int semop(int semid, struct sembuf semoption[], size_t nops);
semget()函数创建一个新的信号量集合或获取一个已经存在的信号量集合,具体参数及实现就不说了,自己去man一下就行了
semctl()函数实现对信号集中的信号进行操作,基本就是初始化设置(比如设置信号量值)、获取先好量的各种参数,删除信号量集合
semop()函数实现在操作共享资源前的检查信号量的值,大于0则获得该共享资源的操作权并将信号减sem_op,或使用完共享资源后将信号量加sem_op
实例:
实例中子进程与父进程都向屏幕打印20个字母,采用信号量使之能够按我们预想的哪像打印,而不会打印乱序
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
int
main(int argc, char** argv)
{
key_t key;
pid_t pid;
int semid;
struct sembuf semoption[1];
union semun
{
int val;
struct semid_ds *buf;
unsigned short *array;
}s;
key=ftok("/tmp/1234", 'a');
semid=semget(key, 1, IPC_CREAT | 0666);
s.val=1;
semctl(semid, 0, SETVAL, s);
semoption[0].sem_num=0;
semoption[0].sem_op=-1;
semoption[0].sem_flg=SEM_UNDO;
if( (pid=fork())==0)
{
semid=semget(key, 0, IPC_CREAT | 0666);
semop(semid, semoption, 1);
int i;
for( i=0; i<20; i++)
printf("A-\n");
semoption[0].sem_op=1;
semop(semid, semoption, 1);
return(0);
}
semop(semid, semoption, 1);
int i=0;
for( ; i<20; i++)
printf("B-\n");
semoption[0].sem_op=1;
semop(semid, semoption, 1);
sleep(1);
semctl(semid, 0, IPC_RMID);
}
二、互斥量
互斥量利用了pthread_mutex_t支持进程间共享的特性,将互斥量设置PTHREAD_PROCESS_SHARED,但是好要共享内存的配合,将互斥量放置于共享内存,而后多进程在读取共享资源前将检查mutex互斥量,如同线程斥量一般。
linux中实现所调用的函数:
int pthread_mutexattr_getpshared(const pthread_mutexattr_t *restrict attr, int *restrict pshared);//mutxeattr设置PTHREAD_PROCESS_SHARED
int pthread_mutex_init(const pthread_mutex_t *restrict mutex, const pthread_mutexattr_t *resrict attr);//初始话互斥量mutex
int shmget(key_t key, size_t size, int flag);//创建共享存储标识或则获取共享存储标识
int shmctl(int shmid, int cmd, struct shmid_ds *buf);//控制共享存储段,获取存储段信息(IPC_STAT)、设置存储段信息(IPC_SET)、删除存储段(IPC_RMID)
int shmat(int shmid, const void *addr, int flag);// 将共享存储段链接到进程的地址上(类似于mmap,不过mmap链接的是命名的文件而shmat映射的是匿名内存)
int shmdt(const void *addr);//将共享存储从进程上断开分离
实例:
此实例中共享存储段中放置了互斥来量和一个int整数用来测试,进程先lock互斥量后将操作整数而后unlock
#include <pthread.h>
#include <string.h>
#include <unistd.h>
#include <sys/ipc.h>
#include <sys/types.h>
#include <stdlib.h>
#include <sys/shm.h>
int *sum=NULL;
int
main(int argc, char** argv)
{
key_t key;
int shmid, size=sizeof(pthread_mutex_t)+sizeof(int);
void *pmen;
pid_t pid;
pid_t mypid;
pthread_mutex_t *pthmutex;
mypid=getpid();
key=ftok("/tmp/1.c", 'b');
if( key==-1)
{
printf("ftok error\n");
return(-1);
}
shmid=shmget(key, size, IPC_CREAT | IPC_EXCL | 0666);
if( shmid==-1)
{
printf("shmget error\n");
return(-1);
}
pthmutex=(pthread_mutex_t*)shmat(shmid, 0, 0);
pthread_mutexattr_t pthattr;
pthread_mutexattr_setpshared(&pthattr, PTHREAD_PROCESS_SHARED);
pthread_mutex_init(pthmutex, &pthattr);
sum=(int*)((void*)pthmutex+sizeof(pthread_mutex_t));
*sum=0;
if( (pid=fork())==0)
{
int cshmid;
void *men;
int *sum;
pthread_mutex_t *pthmutex;
cshmid=shmget(key, size, IPC_CREAT | 0666);
men=shmat(cshmid, 0, 0);
pthmutex=(pthread_mutex_t *)men;
pthread_mutex_lock(pthmutex);
int i;
sum=(int*)((void*)pthmutex+sizeof(pthread_mutex_t));
printf("first sum=%d\n", *sum);
for( i=0; i<50; i++)
(*sum)++;
printf("sum=%d\n", *sum);
pthread_mutex_unlock(pthmutex);
exit(0);
}
pthread_mutex_lock(pthmutex);
printf("second sum=%d\n", *sum);
int j;
for( j=0; j<50; j++)
(*sum)++;
printf("sum=%d\n", *sum);
pthread_mutex_unlock(pthmutex);
shmctl(shmid, IPC_RMID, NULL);
}
- 进程间互斥
- 进程间互斥 Mutex
- 进程间互斥 Mutex
- 进程间互斥CreateEvent
- 进程间互斥CreateMutex
- 进程间互斥CreateMutexTRUE
- 进程间互斥CreateSemaphore
- IPC之进程间互斥
- 进程间互斥与同步
- 进程间互斥、同步
- 进程
- 进程
- 进程
- 进程
- 进程
- 进程
- 进程
- 进程
- ARM汇编指令学习 - 实现数据块的拷贝复制
- CentOS 6.5 Web环境配置
- LeetCodet题解--17. Letter Combinations of a Phone Number(所有数字键盘组合所对应的所有字符集合)
- MySQL数据导出与导入
- 安卓简单的POST和GET请求
- 进程间互斥
- 什么是面向对象设计OOD?
- 我的C语言笔记之经典代码(一)
- 利用elasticsearch的morelikethis功能实现基于内容的相关度推荐
- dpdk helloworld代码分析
- 9—patch图的制作方法
- Tomcat配置多个虚拟主机、部署多个项目
- 页面Tab切点击切换
- Mac OS X系统下修改wifi共享的默认网段