#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;
}
compile it and run
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
here is my program, I make a buffer in parent process, then fork a child process to read the buffer and the parent process start to wait for a semaphore posted by child process, parent process will change the content of buffer after receive semaphore and notify child process to read it again, but my program shows child process read the old content of buffer, according to fork()
's cow
, child process doesn't change the content of buffer then it should read the newest content from it, isn't it?