进程通信
一、使用fork方法系统调用创建进程
fork说明
fork系统调用是用于创建进程的;
fork创建的进程初始化状态和父进程一样;
系统会为fork的进程分配新的资源;
fork调用和返回
fork系统调用无参数;
会返回两次,分别返回子进程ID和零;
返回子进程ID的是父进程,返回0的是子进程;
进程使用example:
#include <iostream>#include <cstring>#include <stdio.h>#include <unistd.h>using namespace std;int main(){int num = 888;pid_t pid;pid = fork();//一次执行,fork会返回两次if(pid == 0){//表示输出一个回车,并刷新输出流,和printf("\n")显示一样cout << "这是一个子进程." << endl;cout << "num is son process:" << num << endl;while(true){num += 1;cout << "num is son process:" << num << endl;sleep(1);}}else if(pid > 0){cout << "这是一个父进程." << endl;cout << "子进程id:" << pid << endl;cout << "num is father process:" << num << endl;while(true){num -= 1;cout << "num is father process:" << num << endl;sleep(1);}}else if(pid < 0){//进程没有创建成功cout << "创建进程失败." << endl;}return 0;}// g++ fork_demo.cpp -o fork_demo -g
二、进程同步之共享内存
(1)、进程和线程
进程的线程共享进程资源
进程之间共享计算机资源
在某种程度上,多进程是共同使用物理内存的;
由于操作系统的进程管理,进程间的内存空间是独立的,是段页式存储管理;
进程默认是不能访问进程空间之外的内存空间的;
-(2)、共享内存共享内存允许不相关的进程访问同一片物理内存;
共享内存是两个进程之间共享和传递数据最快的方式;
共享内存未提供同步机制,需要借助其他机制管理访问;
(3)原理:
申请共享内存
—>连接到进程空间
—>使用共享内存
—>脱离进程空间 &删除example:使用一个带有客户端和服务端的例子通过共享内存来实现通信
server :
client:
common:
#include "common.h"#include <sys/shm.h>#include <stdlib.h>#include <unistd.h>#include <stdio.h>#include <string.h>#include <iostream>int main(){//定义共享内存结构体struct ShmEntry *entry;//1、申请共享内容,参数为key,size和shmfig[IPC_CREAT|(IPC_CREAT|IPC_EXCL)],返回一个共享内存的idint shmid = shmget((key_t)1111,sizeof(struct ShmEntry),0666|IPC_CREAT);if(shmid == -1){std::cout << "创建共享内存失败" << std::endl;return -1;}//2、连接到当前进程空间,使用共享内存//参数共享内存标识符、shmid指定共享内存出现在进程内存地址的什么位置,shmaddr直接指定为NULL让内核自己决定一个合适的地址位置,shmflg读写模式entry = (ShmEntry*)shmat(shmid,0,0);entry->can_read = 0;while(true){if(entry->can_read == 1){std::cout << "收到信息:" << entry->msg << std::endl;entry->can_read = 0;}else{std::cout << "内存块不可读,休息中1s.." << std::endl;sleep(1);}}//3、脱离进程空间//是用来断开与共享内存附加点的地址,禁止本进程访问此片共享内存shmdt(entry);//4、删除共享内存shmctl(shmid,IPC_RMID,0);return 0;}//g++ server.cpp common.h -o server -g -lpthread
#include "common.h"#include <sys/shm.h>#include <stdlib.h>#include <unistd.h>#include <stdio.h>#include <string.h>#include <iostream>int main(){//定义共享内存结构体struct ShmEntry *entry;//1、申请共享内容,参数为key,size和shmfig[IPC_CREAT|(IPC_CREAT|IPC_EXCL)],返回一个共享内存的idint shmid = shmget((key_t)1111,sizeof(struct ShmEntry),0666|IPC_CREAT);if(shmid == -1){std::cout << "创建共享内存失败" << std::endl;return -1;}//2、连接到当前进程空间使用共享内存//参数共享内存标识符、shmid指定共享内存出现在进程内存地址的什么位置,shmaddr直接指定为NULL让内核自己决定一个合适的地址位置,shmflg读写模式entry = (ShmEntry*)shmat(shmid,0,0);entry->can_read = 0;char buffer[TEXT_LEN];while(true){if(entry->can_read == 0){std::cout << "输入信息:>>>";fgets(buffer, TEXT_LEN, stdin);/*trncpy函数用于将指定长度的字符串复制到字符数组中,dest -- 指向用于存储复制内容的目标数组。src -- 要复制的字符串。n -- 要从源中复制的字符数*/strncpy(entry->msg,buffer,TEXT_LEN);std::cout << "发送信息: " << entry->msg << std::endl;entry->can_read = 1;}}//3、脱离进程空间//是用来断开与共享内存附加点的地址,禁止本进程访问此片共享内存shmdt(entry);//4、删除共享内存shmctl(shmid,IPC_RMID,0);return 0;}//g++ client.cpp common.h -o client -g -lpthread
#ifndef __COMMON_H__//if not define的简写#define __COMMON_H__#define TEXT_LEN 2048//共享内存的数据结构struct ShmEntry{//是否可以读取共享内存,用于进程间通信bool can_read;//共享内存信息char msg[2048];};#endif
三、进程同步之unix域套接字
(1)、域套接字是一种高级的进程间通信的方法;
Unix域套接字可以用于同一机器进程间通信;
提供了简单可靠的单机进程通信同步服务,但是只能在单机使用,不能跨机器使用;
(2)、套接字(socket)原是网络通信中使用的术语;
Unix系统提供的域套接字提供了网络套接字类似的功能;
使用有如nginx,uWSGI,,mysql…
(3)、使用:
server:
创建套接字
—>绑定(bind)套接字
—>监听(listen)套接字
—>接受&处理信息
—>关闭client:
创建套接字
—>连接套接字
—>发送消息
—>关闭example:(域套接字的例子)
server:
client:
#include <stdio.h>#include <sys/types.h>#include <sys/socket.h>#include <sys/un.h>#include <strings.h>#include <string.h>#include <netinet/in.h>#include <stdlib.h>#include <unistd.h>#include <iostream>//域套接字定义#define SOCKET_PATH "./domainsocket"#define MSG_SIZE 2048int main(){int socket_fd,accept_fd;int ret = 0;socklen_t addr_len;char msg[MSG_SIZE];struct sockaddr_un server_addr;//1、创建域套接字socket_fd = socket(PF_UNIX,SOCK_STREAM,0);if(-1 == socket_fd){std::cout << "套接字创建失败" << std::endl;return -1;}//移除已有套接字路径remove(SOCKET_PATH);//内存区域置零bzero(&server_addr,sizeof(server_addr));server_addr.sun_family = PF_UNIX;strcpy(server_addr.sun_path,SOCKET_PATH);//2、绑定域套接字std::cout << "绑定套接字..." << std::endl;ret = bind(socket_fd,(sockaddr *)&server_addr,sizeof(server_addr));if(0 > ret){std::cout << "绑定套接字失败" << std::endl;return -1;}//3、监听套接字std::cout << "监听套接字..." << std::endl;ret = listen(socket_fd,10);if(-1 == ret){std::cout << "监听套接字失败" << std::endl;return ret;}std::cout << "等待新的请求." << std::endl;accept_fd = accept(socket_fd,NULL,NULL);bzero(msg,MSG_SIZE);//true必须小写while(true){//4、接受&处理信息recv(accept_fd,msg,MSG_SIZE,0);std::cout << "接受信息:" << msg << std::endl;}close(accept_fd);close(socket_fd);return 0;}//g++ server.cpp -o server -g -lpthread
#include <stdio.h>#include <sys/types.h>#include <sys/socket.h>#include <sys/un.h>#include <strings.h>#include <string.h>#include <netinet/in.h>#include <stdlib.h>#include <unistd.h>#include <iostream>//域套接字定义#define SOCKET_PATH "./domainsocket"#define MSG_SIZE 2048int main(){int socket_fd,accept_fd;int ret = 0;socklen_t addr_len;char msg[MSG_SIZE];struct sockaddr_un server_addr;//1、创建域套接字socket_fd = socket(PF_UNIX,SOCK_STREAM,0);if(-1 == socket_fd){std::cout << "套接字创建失败" << std::endl;return -1;}//内存区域置零bzero(&server_addr,sizeof(server_addr));server_addr.sun_family = PF_UNIX;strcpy(server_addr.sun_path,SOCKET_PATH);//2、连接域套接字std::cout << "2、连接套接字..." << std::endl;ret = connect(socket_fd,(sockaddr *)&server_addr,sizeof(server_addr));if(0 > ret){std::cout << "连接套接字失败" << std::endl;return -1;}while(true){//键入信息std::cout << "键入信息>>>";fgets(msg,MSG_SIZE,stdin);//3、发送消息ret = send(socket_fd,msg,MSG_SIZE,0);}close(socket_fd);return 0;}//g++ client.cpp -o client -g -lpthread
文章转载自智慧大数据,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。




