共享内存
- 本质:同一块物理内存映射到不同的虚拟地址空间,访问的时候和访问普通内存没什么差别。但是共享内存是进程间通信的最快的形式。
- 内存映射到共享它的进程的地址空间,那么数据间的传递不再涉及到内核。
共享内存函数的介绍:https://blog.csdn.net/guoping16/article/details/6584058
共享内存没有进行同步与互斥
- 共享内存用于任意进程之间
- 双向通信,全双工
- 没有面向字节流,随机访问。
信号量
- 本质:计数器(可用资源的个数,用s表示,=0则表示没有可用的资源,无等待进程)
struct semaphore
{
int value; //可用资源个数
pointer_pcb queue;
}
- 系统中的某些资源只允许一个进程使用,这样的资源称为临界资源或者是互斥资源
- 互斥说明在一个进程中,同步说明在不同的进程中
- 而、
- pv操作:p是申请资源,v是释放资源。
- 相关的函数介绍 https://blog.csdn.net/guoping16/article/details/6584043
用信号量实现PV操作
sem.c源代码如下:
#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
union semun {
int val; /* value for SETVAL */
struct semid_ds *buf; /* buffer for IPC_STAT, IPC_SET */
unsigned short *array; /* array for GETALL, SETALL */
struct seminfo *__buf; /* buffer for IPC_INFO */
};
/***对信号量数组semnum编号的信号量做P操作***/
int P(int semid, int semnum)//这里的参数分别是信号量标识码和执行的顺序优先级
{
struct sembuf sops={semnum,-1, SEM_UNDO};
return (semop(semid,&sops,1));
}
/***对信号量数组semnum编号的信号量做V操作***/
int V(int semid, int semnum)
{
struct sembuf sops={semnum,+1, SEM_UNDO};
return (semop(semid,&sops,1));
}
int main(int argc, char **argv)
{
int key ;
int semid,ret;
union semun arg;
struct sembuf semop;
int flag ;
key = ftok("/tmp", 0x66 ) ;//获取ID
if ( key < 0 )
{
perror("ftok key error") ;
return -1 ;
}
semid = semget(key,1,IPC_CREAT|0600);//创建一个信号量
if (semid == -1)
{
perror("create semget error");
return ;
}
if ( argc == 1 )
{
arg.val = 1;
ret =semctl(semid,0,SETVAL,arg);//设置0信号量的计数值为1
if (ret < 0 )
{
perror("ctl sem error");
semctl(semid,0,IPC_RMID,arg);
return -1 ;
}
}
/***取0号信号量的值***/
ret =semctl(semid,0,GETVAL,arg);
printf("after semctl setval sem[0].val =[%d]\n",ret);
system("date") ;
printf("P operate begin\n") ;
flag = P(semid,0) ; //p操作
if ( flag )
{
perror("P operate error") ;
return -1 ;
}
printf("P operate end\n") ;
ret =semctl(semid,0,GETVAL,arg);
printf("after P sem[0].val=[%d]\n",ret);
system("date") ;
if ( argc == 1 )
{
sleep(120) ;
}
printf("V operate begin\n") ;
if (V(semid, 0) < 0) //v操作
{
perror("V operate error") ;
return -1 ;
}
printf("V operate end\n") ;
ret =semctl(semid,0,GETVAL,arg);
printf("after V sem[0].val=%d\n",ret);
system("date") ;
if ( argc >1 )
{
semctl(semid,0,IPC_RMID,arg);
}
return 0 ;
}
- 可用于任意的进程,生命周期随内核