一、进程同步
1、比较
- 进程间数据共享: 管道,消息队列,共享内存,unix 域套接字
对比:
- 易用性:消息队列 > unix 域套接字 > 管道 > 共享内存(配合信号量使用)
- 效率:共享内存 > unix 域套接字 > 管道 > 消息队列
- 常用:共享内存,unix 域套接字
2、共享内存实现
- 进程空间是通过页表,通过段页式存储管理,与实际物理内存建立的映射;
- 所以进程间也是公用物理内存的;
- 操作系统的进程管理,使得进程间内存空间独立;进程默认是不能访问进程空间之外的内存空间的;
共享内存:
- 共享内存,允许不相关的进程访问同一片物理内存;
- 共享内存是两个进程之间共享和传递数据最快的方式;
- 共享内存未提供同步机制,需要借助其他机制管理访问;
使用共享内存:
- 申请共享内存 : shmget((key_t)1111,sizeof(struct ShmEntry),0666|IPC_CREAT);
- 连接到进程空间 : (ShmEntry*)shmat(shmid,0,0);连接到
- 使用共享内存
- 脱离进程空间&& 删除 : shmdt(entry); && shmctl(shmid,IPC_RMID,0);
#ifndef __COMMON_H_
#define __COMMON_H_
#define TEXT_LEN 2048
struct ShmEntry{
bool can_read;
char msg[2048];
};
#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;
int shmid = shmget((key_t)1111,sizeof(struct ShmEntry),0666|IPC_CREAT);
if(shmid ==-1)
{
std::cout<<"creat error!"<<std::endl;
return -1;
}
std::cout<<"yes! "<<std::endl;
entry = (ShmEntry*)shmat(shmid,0,0);
entry->can_read = 0;
while(true){
if(entry->can_read == 1)
{
std::cout<<"msg : "<<entry->msg<<std::endl;
entry->can_read = 0;
}
else
{
std::cout<<" sleep 1 second"<<std::endl;
sleep(1);
}
}
shmdt(entry);
shmctl(shmid,IPC_RMID,0);
return 0;
}
#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;
int shmid = shmget((key_t)1111,sizeof(struct ShmEntry),0666|IPC_CREAT);
if(shmid ==-1)
{
std::cout<<"creat error!"<<std::endl;
return -1;
}
std::cout<<"yes! "<<std::endl;
entry = (ShmEntry*)shmat(shmid,0,0);
entry->can_read = 0;
char buffer[TEXT_LEN];
while(true){
if(entry->can_read == 0)
{
std::cout<<"input message: "<<std::endl;
fgets(buffer,TEXT_LEN,stdin);
strncpy(entry->msg,buffer,TEXT_LEN);
entry->can_read = 1;
}
}
shmdt(entry);
shmctl(shmid,IPC_RMID,0);
return 0;
}
g++ server .cpp common.h -o server -g -lpthread
g++ client.cpp common.h -o client -g -lpthread
- 实现

3、Unix 域套接字实现
- 套接字本是网络通信;
- Unix系统提供的域套接字提供了网络套接字类似功能;
- 他提供了单机、简单、可靠的进程通信同步服务;
- 只能单机使用,不能跨机器使用;跨机器需要网络套接字;
- 相比共享内存,提供的是可靠的信息传递,不需要维护同步信息;
- Nginx 、 uWSGI 、 都会使用到;
server使用:
- 创建套接字
- 绑定套接字
- 监听套接字
- 接收&处理信息
client使用:
- 创建套接字
- 连接套接字
- 发送信息
#include <sys/types.h>
#include <sys/un.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <strings.h>
#include <netinet/in.h>
#include <iostream>
#define SOCKET_PATH "./domainsocket"
#define MSG_SIZE 2048
using namespace std;
int main()
{
int socket_fd, accept_fd;
int ret = 0;
socklen_t addr_len;
char msg[MSG_SIZE];
struct sockaddr_un server_addr;
socket_fd = socket(PF_UNIX,SOCK_STREAM,0);
if (-1 == socket_fd)
{
cout << "socket create failed" << 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);
cout << "binding " << endl;
ret = bind(socket_fd, (sockaddr*)&server_addr, sizeof(server_addr));
if (0 > ret)
{
cout << "bind socket failed" << endl;
return -1;
}
cout << "listening " << endl;
ret = listen(socket_fd, 10);
if (-1 == ret)
{
cout << "listen failed" << endl;
return -1;
}
cout << "waiting new requests " << endl;
accept_fd = accept(socket_fd, NULL, NULL);
bzero(msg, MSG_SIZE);
while (1)
{
recv(accept_fd, msg, MSG_SIZE, 0);
cout << "received message : " << msg<<endl;
}
close(accept_fd);
close(socket_fd);
return 0;
}
#include <sys/types.h>
#include <sys/un.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <strings.h>
#include <netinet/in.h>
#include <iostream>
#define SOCKET_PATH "./domainsocket"
#define MSG_SIZE 2048
using namespace std;
int main()
{
int socket_fd;
int ret = 0;
char msg[MSG_SIZE];
struct sockaddr_un server_addr;
socket_fd = socket(PF_UNIX,SOCK_STREAM,0);
if (-1 == socket_fd)
{
cout << "socket create failed" << endl;
return -1;
}
bzero(&server_addr, sizeof(server_addr));
server_addr.sun_family = PF_UNIX;
strcpy(server_addr.sun_path, SOCKET_PATH);
cout << "connecting " << endl;
ret = connect(socket_fd, (sockaddr*)&server_addr, sizeof(server_addr));
if (-1 == ret)
{
cout << "bind socket failed" << endl;
return -1;
}
while (1)
{
cout << "Input message >>> ";
fgets(msg, MSG_SIZE, stdin);
ret = send(socket_fd, msg, MSG_SIZE,0);
}
close(socket_fd);
return 0;
}
g++ server.cpp -o server -g -lpthread
g++ client.cpp -o client -g -lpthread
实现: 
参考
【学习笔记】【操作系统】
|