0914共享内存通信

 

共享内存通信:允许两个不相干的进程访问同一个逻辑内存,让连个正在运行的进程传输数据的有效方式。
原理:进程有特定的的进程控制块和地址空间和与空间对应的页表,页表将虚拟地址和物理地址进行映射,通过内存管理MMU管理,不同的虚拟地址通过页表映射至物理空间的同一地址。

函数ipcs
相关头文件<sys/ipc.h> <sys/shm.h>
查看共享存储段:ipcs -m
删除共享存储段:ipcrm -m [shmid]

shmget()创建共享内存:int shmget(key_t key(标识系统的唯一IPC资源),size_t size(共享内存大小),int shmflg(设置访问权限比如0641)|IPC_CREAT);创建情况下还须追加IPC_CREAT
成功返回一个共享标识符
失败返回-1
shmat()挂件共享内存
void *shmat(int shmid(共享内存段标识符),const void *shmaddr(NULL,则存储段连接到由内核选择的第一个地址上),int shmflg(设定权限));
成功返回指针/虚拟地址 失败返回-1
shmctl()销毁共享内容
int shmctl(int shmid(共享存储段标识符),int cmd(指定的执行操作,IPC_RMID),struct shmid_ds *buf(NULL));

例程:

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h> 
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/shm.h>
#include <sys/ipc.h>

#define SHMKEY 75	//定义键值,也可通过ftok进行生成

int shmid, i;
int *addr=NULL;
void client(void) 
{
	int i; 
	shmid = shmget(SHMKEY, 1024, 0777);//获得已有的共享内存段 
	if(shmid==-1)
	{
		printf("client()... shmget() fail!\n");
		exit(1);
	}
	printf("client() shmid=%d\n",shmid);

	addr = (int *)shmat(shmid, NULL, 0);//挂接共享内存
	for(i=9;i>=0;i--)
	{
		while(-1 != *addr) ;//addr的内容是-1,就跳出循环
		printf("(client) server save *addr=%d\n",*addr);
		*addr= i;
		printf("(client) sent *addr=%d\n",i);
	}
	exit(0);
}


void server(void) 
{
	//shmget()创建共享内存段
	//参1:SHMKEY=75
	//参2:1024字节
	//参3:授予权限|IPC_CREAT
	shmid = shmget(SHMKEY, 1024, 0777 | IPC_CREAT);
	if(shmid==-1)
	{
		printf("servre()...shmget() fail!\n");
		exit(1);
	}
	printf("server() shmid=%d\n",shmid);
	//addr: 前面定义的是 int *addr
	//shmat()挂载共享内存段
	//参1:shmid,共享内存段标识符
	//参2:NULL 采用系统默认
	//参3: 控制读写权限,0:可以读写,SHM_RDONLY:只读
	addr = (int *)shmat(shmid, NULL, 0);
	do
	{
		*addr= -1;
		while (*addr== -1) ;//addr里面的内容==-1,则死循环此句
		printf("(server) received addr的内容=%d\n",*addr);
	} while (*addr);//*addr不等于0,继续循环
	shmctl(shmid, IPC_RMID, 0);
	exit(0);
}

int main()
{
	while (-1 == (i = fork())) ;//直到创建新进程成功,才会下一步
	if(!i)//i==0时,条件成立,进入子1进程
	{
		server();//server()功能由子1进程完成
	}
	system("ipcs -m");//同时父进程:调用ipcs命令查看IPC
	while (-1 == (i= fork())) ;
	if(!i)
	{
		client();//client()功能由子2进程完成 
	}
	wait(NULL);//等子进程结束
	wait(NULL);//等子进程结束
	
	system("ipcs -m");
	return 0;
}


进程组和会话

进程组:一个或多个进程的集合,通常与一组作业相关联,可以接受来自同一终端的信号
getpgrp:获取进程组id,即领头进程id
相关头文件<unistd>
pid_t getpgrp(void);    返回调用进程组ID
printf("%d\n",getgpid);打印进程组id

创建会话

调用进程不能是进程组组长,该进程变成新绘画首进程
该进程成为一个新进程组的组长进程
新会话丢弃原有的控制终端(转入后台)
调用进程为组长进程则出错

getsid函数 pid_t getsid(pid_t pid)
成功返回进程会话ID,失败返回-1
setsid函数 pid_t setsid(void)
setsid函数的进程,是新的组长和会长
setsid后pgid和sid都被改变

守护进程:一类在后台运行,执行特定的工作。在系统启动时启动,运行至系统关闭。必要时启动,完成后自动关闭
不受任何终端控制
创建
创建子进程,父进程退出
父进程必须终止,之前孤儿进程变成主要进程
在子进程中创建新会话:setsid()使子进程独立出来,脱离控制
改变当前目录chdir(绝对路径):防止占用可卸载的文件系统,也可以换成其他路径
重设文件权限掩码umask(文件访问权限掩码比如00(可读可写)2(写)2)
关闭文件描述符close(文件描述符)
将标准输入标准输出标准错误全部重定向至/dev/null
fd=open("/dev/null",O_RDWR);fd指向0
while(1)模拟守护进程业务逻辑要求

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值