【发布时间】:2026-01-31 16:00:01
【问题描述】:
#include <fcntl.h>
#include <semaphore.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/stat.h> /* For mode constants */
#include <sys/types.h>
#include <unistd.h>
#include <iostream>
#include <thread>
using namespace std;
const char* shm_path = "conn_close_test";
char buf[] = "666";
int main() {
sem_t* sem_child;
sem_t* sem_parent;
// int flag = O_CREAT | O_EXCL | O_RDWR;
int flag = O_CREAT | O_RDWR;
// create share memory object
int fd = shm_open(shm_path, flag, S_IRUSR | S_IWUSR);
if (fd == -1) {
std::cout << "create failed for reason: " << strerror(errno) << std::endl;
return -1;
}
int page_size = 4096;
if (ftruncate(fd, page_size * 2) == -1) {
std::cout << "ftruncate failed : " << strerror(errno) << std::endl;
return -1;
}
// create semphore
sem_child = (sem_t*)mmap(NULL, sizeof(sem_t), PROT_READ | PROT_WRITE,
MAP_SHARED, fd, 0);
if ((__int64_t)(sem_child) == -1) {
std::cout << "mmap sem child failed for reason:" << strerror(errno)
<< std::endl;
}
sem_parent = (sem_t*)mmap(NULL, sizeof(sem_t), PROT_READ | PROT_WRITE,
MAP_SHARED, fd, page_size);
if ((__int64_t)(sem_parent) == -1) {
std::cout << "mmap sem parent failed for reason:" << strerror(errno)
<< std::endl;
}
int ret = sem_init(sem_child, 1, 0);
if (ret == -1) {
std::cout << "sem_child sem_init failed for: " << strerror(errno)
<< std::endl;
return -1;
}
ret = sem_init(sem_parent, 1, 0);
if (ret == -1) {
std::cout << "sem_parent sem_init failed for: " << strerror(errno)
<< std::endl;
return -1;
}
// fork
pid_t pid = fork();
if (pid == 0) {
// child process read buf first then post a semophore to wakeup parent process
std::cout << "children first read\n";
std::cout << "buf: " << buf << std::endl;
std::cout << "sem_child post to wake up parent process" << std::endl;
sem_post(sem_child);
std::cout << "child process waiting for sem_parent" << std::endl;
sem_wait(sem_parent);
std::cout << "children second read\n";
std::cout << "buf: " << buf << std::endl;
} else if(pid > 0 ){
std::cout << "parent process waiting for sem_child\n";
sem_wait(sem_child);
std::cout << "parent first read\n";
std::cout << "buf: " << buf << std::endl;
buf[0] = buf[1] = buf[2] = '7';
std::cout<<"modify buf "<<std::endl;
std::cout << "buf: " << buf << std::endl;
std::cout<<"sem_parent post to wake up child process"<<std::endl;
sem_post(sem_parent);
}
return 0;
}
编译并运行
chenbh@ubuntu:~/projects/conn_close_test$ g++ sem_test.cpp -lrt -lpthread -O0 -g
chenbh@ubuntu:~/projects/conn_close_test$ ./a.out
parent process waiting for sem_child
children first read
buf: 666
sem_child post to wake up parent process
child process waiting for sem_parent
parent first read
buf: 666
modify buf
buf: 777
sem_parent post to wake up child process
children second read
buf: 666
这是我的程序,我在父进程中创建一个缓冲区,然后派生一个子进程来读取缓冲区,并且父进程开始等待子进程发布的信号量,父进程将在接收后更改缓冲区的内容信号量并通知子进程再次读取它,但我的程序显示子进程读取缓冲区的旧内容,根据fork()的cow,子进程不会更改缓冲区的内容那么它应该读取最新的内容,不是吗?
【问题讨论】:
-
fork使用父地址空间的副本创建一个新进程。更改父进程中的buf不会更改子进程中的buf。 -
if ((__int64_t)(sem_child) == -1)?!?!?你为什么错误地尝试重塑MAP_FAILED? -
这能回答你的问题吗? Using shared memory with fork()
-
我认为这是一个误解,正如 kaylum 已经提到的那样。
cow代表copy-on-write。 -
buf [],应该在共享内存里面。现在它只是一个全局变量。 parent 和 child 的地址空间不同。所以buf在父子进程中是不同的。