例子1:两个进程通过共享内存通信,一个进程向共享内存中写入数据,另一个进程从共享内存中读出数据

    文件1 创建进程1,实现功能,打印共享内存中的数据

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <errno.h>
#include <string.h> int main(int argc, const char *argv[])
{
key_t key;
int shmid;
char *p = NULL; // key_t ftok(const char *pathname, int proj_id);;
key = ftok("./app",'b'); //获取唯一的 key 值,
if(key < )
{
perror("fail ftok ");
exit();
} shmid = shmget(key, , IPC_CREAT|IPC_EXCL|);//创建/打开共享内存,返回id根据id映射
if(shmid < )
{
if(errno == EEXIST)//文件存在时,直接打开文件获取shmid
{
printf("file eexist");
shmid = shmget(key,,);
}
else
{
perror("shmget fail ");
exit();
}
}
p = (char *)shmat(shmid,NULL,);//映射,返回地址,根据地址操作
if( p == (char *)(-) )
{
perror("shmat fail ");
exit();
} while()
{
sleep();
printf("P:%s",p);
if(strstr(p,"quit") != NULL) //接收到 quit 结束循环
{
break;
}
}
shmdt(p);//解除映射 //函数原型 int shmctl(int shmid, int cmd, struct shmid_ds *buf);
shmctl(shmid,IPC_RMID,NULL); //删除
return ;
}

  文件2  创建进程2 实现功能,获取终端输入的数据写到共享内存中,这两个进程需要同时启动才可以实现通信

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <errno.h>
#include <string.h> int main(int argc, const char *argv[])
{
key_t key;
int shmid;
char *p = NULL;
// key_t ftok(const char *pathname, int proj_id);;
key = ftok("./app",'b'); //创建key值,
if(key < )
{
perror("fail ftok ");
exit();
}
shmid = shmget(key,,IPC_CREAT|IPC_EXCL|);//创建/打开共享内存,返回id根据id映射
if(shmid < )
{
if(errno == EEXIST)//文件存在时,直接打开文件获取shmid
{
printf("file eexist");
shmid = shmget(key,,); //共享内存存在时,直接打开
}
else
{
perror("shmget fail ");
exit();
}
}
p = (char *)shmat(shmid,NULL,);//映射,返回地址,根据地址操作
if( p == (char *)(-) )
{
perror("shmat fail ");
exit();
}
while() //接收到 quit 结束循环
{
//read 时p中 内容不会清空
//read(0,p,10);//终端读数据,写入p指向的空间,读取数据时不会清空
fgets(p,,stdin);
if(strstr(p,"quit") != NULL)
{
break;
}
}
shmdt(p);//解除映射 //函数原型 int shmctl(int shmid, int cmd, struct shmid_ds *buf);
shmctl(shmid,IPC_RMID,NULL); //删除
return ;
}

测试:在进程2终端下输入数据,会在进程1 的终端下打印出来,但是一直打印(输入quit退出循环)

 

例子2 :使用信号灯集访问临界资源(共享内存)处理上面的一直循环打印的问题

通过创建包含 2 个信号灯的灯集, 分别控制两个进程访问共享内存  ( 2值信号灯 )

文件 1  进程1 通过终端输入数据写入共享内存, 两个信号灯,先允许通过终端 输入数据进程操作

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <errno.h>
#include <string.h>
#include <sys/sem.h> int semid; //信号灯集id
union semnum
{
int val; //信号灯值
}; union semnum mynum; struct sembuf mybuf; //定义操作信号灯的结构,PV操作,哪个灯 //参数 信号灯集id 和 是哪个信号灯
void sem_p(int semid, unsigned short num) //P操作函数
{
mybuf.sem_num = num; //第一个信号灯,(信号灯编号)
mybuf.sem_op = -; //进行P操作, 为 1 时表示V操作
mybuf.sem_flg = ; //阻塞,表示semop函数的操作是阻塞的,直到成功为止
semop(semid, &mybuf, ); //最后一个参数,表示操作信号灯的个数
} //参数 信号灯集id 和 是哪个信号灯
void sem_v(int semid, unsigned short num) //V操作函数
{
mybuf.sem_num = num;
mybuf.sem_op = ; //1 表示V 操作
mybuf.sem_flg = ; //阻塞,表示semop函数的操作是阻塞的,直到操作成功为止
semop(semid, &mybuf, ); //操作的 mybuf 全部变量信号灯集
} int main(int argc, const char *argv[])
{
key_t key;
int shmid;
char *p = NULL; // key_t ftok(const char *pathname, int proj_id);;
key = ftok("./app",'b'); //创建key值,
if(key < )
{
perror("fail ftok ");
exit();
} //IPC_EXCL | IPC_CREAT 信号灯不存在就创建
semid = semget(key, , IPC_CREAT|IPC_EXCL|); //创建信号灯,IPC_EXCL 问信号灯存不存在
if(semid < )
{
if(errno == EEXIST)//存在时,只需要打开即可
{
semid = semget(key,,); //打开信号灯
}
else
{
perror("semget fail ");
       exit(1);
}
}
else
{
mynum.val = ; //设置信号灯值
semctl(semid,,SETVAL,mynum); //初始化一个信号灯 mynum.val = ;
semctl(semid,,SETVAL,mynum);
} shmid = shmget(key,,IPC_CREAT|IPC_EXCL|);//创建/打开共享内存,返回id根据id映射
if(shmid < )
{
if(errno == EEXIST)//文件存在时,直接打开文件获取shmid
{
printf("file eexist");
shmid = shmget(key,,); // 直接打开共享内存
}
else
{
perror("shmget fail ");
exit();
}
} p = (char *)shmat(shmid,NULL,);//映射,返回地址,根据地址操作
if( p == (char *)(-) ) //判断共享内存是否正确
{
perror("shmat fail ");
exit();
}
while()
{
sem_p(semid, ); // P 操作
//read 时 p 指向的共享内存中内容不会清空
//read(0,p,10);//终端读数据,写入p指向的空间,读取数据时不会清空
fgets(p,,stdin);
sem_v(semid, ); // V 操作
if(strstr(p,"quit") != NULL) //当输入 "quit" 退出循环
{
break;
}
}
shmdt(p);//解除映射 //int shmctl(int shmid, int cmd, struct shmid_ds *buf);
shmctl(shmid,IPC_RMID,NULL); //删除共享内存
semctl(semid,,IPC_RMID);//删除信号灯
return ;
}

文件 2  进程2 读取共享内存中的数据, 通过信号灯控制, 当写操作完成时读取一次, 然后等待下次写入

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <errno.h>
#include <string.h>
#include <sys/sem.h> int semid; //信号灯集id
union semnum
{
int val; //信号灯值
}; union semnum mynum; struct sembuf mybuf; //定义操作信号灯的结构 //参数 信号灯集id 和 是哪个信号灯
void sem_p(int semid, unsigned short num) //P操作函数
{
mybuf.sem_num = num; //第一个信号灯,(信号灯编号)
mybuf.sem_op = -; //进行P操作, 为 1 时表示V操作
mybuf.sem_flg = ; //阻塞,表示semop函数操作是阻塞的,直到成功为止
  //函数semop是对信号灯进行PV操作的函数,通过上面的结构体,参数,确定是P操作还是V操作,确定是对哪个信号灯的PV 操作,simid表示操作的是那个信号灯集
semop(semid, &mybuf, ); //最后一个参数,表示操作信号灯的个数
} //参数 信号灯集id 和 是哪个信号灯
void sem_v(int semid, unsigned short num) //V操作函数
{
mybuf.sem_num = num;
mybuf.sem_op = ; //1 表示V 操作
mybuf.sem_flg = ; //阻塞,表示semop函数操作是阻塞的,直到成功为止
semop(semid, &mybuf, ); //操作的 mybuf 全部变量信号灯集
} int main(int argc, const char *argv[])
{
key_t key;
int shmid;
char *p = NULL; // key_t ftok(const char *pathname, int proj_id);;
key = ftok("./app",'b'); //创建key值,
if(key < )
{
perror("fail ftok ");
exit();
} //IPC_EXCL | IPC_CREAT 信号灯不存在就创建
semid = semget(key, , IPC_CREAT|IPC_EXCL|); //创建信号灯,IPC_EXCL 问信号灯存不存在
if(semid < )
{
if(errno == EEXIST)//存在时,只需要打开即可
{
semid = semget(key,,); //打开信号灯
}
else
{
perror("semget fail ");
}
}
else
{
mynum.val = ; //设置信号灯值
semctl(semid,,SETVAL,mynum); //初始化一个信号灯 mynum.val = ;
semctl(semid,,SETVAL,mynum);
} shmid = shmget(key,,IPC_CREAT|IPC_EXCL|);//创建/打开共享内存,返回id根据id映射
if(shmid < )
{
if(errno == EEXIST)//文件存在时,直接打开文件获取shmid
{
printf("file eexist");
shmid = shmget(key,,);
}
else
{
perror("shmget fail ");
exit();
}
}
p = (char *)shmat(shmid,NULL,);//映射,返回地址,根据地址操作
if( p == (char *)(-) )
{
perror("shmat fail ");
exit();
}
while()
{
sleep();
sem_p(semid, );
printf("P:%s",p);
sem_v(semid, );
// write(0,p,10);//向终端写数据,把p指向的空间的内容
if(strstr(p,"quit") != NULL)
{
break;
}
}
shmdt(p);//解除映射 //int shmctl(int shmid, int cmd, struct shmid_ds *buf);
shmctl(shmid,IPC_RMID,NULL); //删除
semctl(semid,,IPC_RMID);//删除信号灯
return ;
}

测试:

例子2中通过两个2值信号灯实现同步操作,先把写数据到共享内存的信号灯初始化值为1,读共享内存的信号灯初始化为0,让写操作的进程先操作共享内存

linux 两个进程通过 共享内存 通信例子的更多相关文章

  1. Windows进程间共享内存通信实例

    Windows进程间共享内存通信实例 抄抄补补整出来 采用内存映射文件实现WIN32进程间的通讯:Windows中的内存映射文件的机制为我们高效地操作文件提供了一种途径,它允许我们在WIN32进程中保 ...

  2. linux使用共享内存通信的进程同步退出问题

    两个甚至多个进程使用共享内存(shm)通信,总遇到同步问题.这里的“同步问题”不是说进程读写同步问题,这个用信号量就好了.这里的同步问题说的是同步退出问题,到底谁先退出,怎么知道对方退出了.举个例子: ...

  3. C# .Net 多进程同步 通信 共享内存 内存映射文件 Memory Mapped 转 VC中进程与进程之间共享内存 .net环境下跨进程、高频率读写数据 使用C#开发Android应用之WebApp 分布式事务之消息补偿解决方案

    C# .Net 多进程同步 通信 共享内存 内存映射文件 Memory Mapped 转 节点通信存在两种模型:共享内存(Shared memory)和消息传递(Messages passing). ...

  4. PHP进程通信基础——信号量+共享内存通信

    PHP进程通信基础--信号量+共享内存通信 由于进程之间谁先执行并不确定,这取决于内核的进程调度算法,其中比较复杂.由此有可能多进程在相同的时间内同时访问共享内存,从而造成不可预料的错误.信号量这个名 ...

  5. C# 进程间共享内存通信方式

    从别处看到一篇文章做进程间通信很好使,唯一的问题是,需要注意using的用法,Using有个用法3, using 语句允许程序员指定使用资源的对象应当何时释放资源.using 语句中使用的对象必须实现 ...

  6. linux c编程:Posix共享内存区

    Posix共享内存区:共享内存是最快的可用IPC形式.它允许多个不相关(无亲缘关系)的进程去访问同一部分逻辑内存.如果需要在两个进程之间传输数据,共享内存将是一种效率极高的解决方案.一旦这样的内存区映 ...

  7. linux下的进程间通信之共享内存

    概念:这种机制允许两个或多个进程通过把公共数据结构放入一个共享内存区来访问它们.如果进程要访问这种数据结构所在的共享内存区,就必须在自己的地址空间中增加一个新线性区,新线性区映射与这个共享内存区相关的 ...

  8. linux下查询进程占用的内存方法总结

    linux下查询进程占用的内存方法总结,假设现在有一个「php-cgi」的进程 ,进程id为「25282」.现在想要查询该进程占用的内存大小.linux命令行下有很多的工具进行查看,现总结常见的几种方 ...

  9. Linux下php-fpm进程过多导致内存耗尽问题

    这篇文章主要介绍了解决Linux下php-fpm进程过多导致内存耗尽问题,需要的朋友可以参考下   最近,发现个人博客的Linux服务器,数据库服务经常挂掉,导致需要重启,才能正常访问,极其恶心,于是 ...

随机推荐

  1. LNMP一键安装包+Thinkphp搭建基于pathinfo模式的路由

    LNMP一键安装包是一个用Linux Shell编写的可以为CentOS/RadHat/Fedora.Debian/Ubuntu/Raspbian/Deepin VPS或独立主机安装LNMP(Ngin ...

  2. Zookeeper-技术专区-运作流程分析介绍

    Zookeeper的启动流程 Zookeeper的主类是QuorumPeerMain,启动时读取zoo.cfg配置文件,如果没有配置server列表,则单机模式启动,否则按集群模式启动,这里只分析集群 ...

  3. 在同一个项目中灵活运用application/json 和application/x-www-form-urlencoded 两种传输格式(配合axios,同时配置loading)

    'use strict' import axios from 'axios' // import qs from 'qs' import { Notification} from 'element-u ...

  4. PAT 乙级练习题1002. 写出这个数 (20)

    1002. 写出这个数 (20) 读入一个自然数n,计算其各位数字之和,用汉语拼音写出和的每一位数字. 输入格式:每个测试输入包含1个测试用例,即给出自然数n的值.这里保证n小于10100. 输出格式 ...

  5. Xversion for Mac优秀的SVN客户端功能特色介绍

    xversion for mac是一款专为macOS打造的svn客户端,该软件拥有一个设计精美的界面以及全面的功能,简介的用户界面可以让您做到无需浏览用户手册即可熟练使用.xversion支持从最开始 ...

  6. js实现复制|剪切指定内容到粘贴板--clipboard

    这是著名开源项目 clipboard.js 的 README.md,里面讲解的更加详细,有兴趣的同学可以了解一下.项目地址:https://github.com/zenorocha/clipboard ...

  7. go导入包

    go导入包 go有很多内置的函数,例如println,不需要引用即可使用.但是如果不借助go的标准库或者第三方库,我们能做的事情有限.在go中,使用关键字import在代码中导入一个包并使用. 修改我 ...

  8. PHP ftp_cdup() 函数

    定义和用法 ftp_cdup() 函数把当前目录改变为 FTP 服务器上的父目录. 如果成功,该函数返回 TRUE.如果失败,则返回 FALSE. 语法 ftp_cdup(ftp_connection ...

  9. Android中的隐藏API和Internal包的使用之获取应用电量排行

    今天老大安排一个任务叫我获取手机中应用耗电排行(时间是前天晚上7点到第二天早上10点),所以在网上各种搜索,没想到这种资料还是很多的,发现了一个主要的类:PowerProfile,但是可以的是,这个类 ...

  10. position:fixed 造成页面抖动解决办法

    今天做项目遇到一个问题.鼠标滚动到指定长度后,理想状况是菜单吸附到顶部.但是实际上在一些页面上会造成抖动.定位之后发现.window.pageYoffset值会变成0 搜索一些资料后发现.因为fixe ...