尝试在客户端-服务器程序中的进程之间创建共享内存段
Trying to create a shared memory segment between processes in client-server program
我正在创建一个使用套接字进行连接的客户端-服务器程序,一旦客户端连接到服务器,就会为客户端创建一个新进程(项目需要)。我在服务器中有一个链接列表,用于存储持有有关它们的信息的客户端结构。
这造成的问题是,例如,当 2 个客户端连接时,每个客户端只能查看其中包含详细信息的链表版本。所以我正在尝试创建一个包含链接列表的共享内存段,但我是共享内存的新手并且正在努力让它工作。
node_t *client_list = NULL;
int main() {
int shmid;
key_t key;
key = 1234;
shmid = shmget(key, SHMSZ, IPC_CREAT | 0666);
client_list = (node_t *) shmat(shmid, (void *)0, 0);
while(1) {
pid_t current_process;
if ((current_process = fork()) == 0) {
node_add(client_list, &client);
node_print(client_list);
pthread_create(&thread[client_count], NULL, network(client.ID), (void *) &client);
}
return 0;
}
(我已将套接字连接代码等关闭以使其更具可读性)。
我可能在当前版本中做错了一些事情,但我的理解是我正在为 'node_t *client_list' 创建共享内存段,这是一个链表,然后在从连接创建新进程后,将客户端节点添加到其中.任何帮助将不胜感激。
对这个问题有点好奇,所以我想把分叉/共享内存和信号量的概念证明放在一起,以防止读取不完整的写入。
我有一些要点:
mmap
似乎是比 sysv 共享内存段更简单、更现代的共享内存实现。
- 需要信号量或其他协调来确保读取完成而写入未完成。
mmap
中的数据是共享的,但如果该数据是一个指针,它必须指向一个 mmap 段,否则它不会在每个 fork 中工作......我很确定。因此,请确保将您的共享数据 all 放入共享内存中,而不仅仅是其地址。
关于使用共享内存的注意事项:我创建了 2 个不同的 mmap
-共享内存,一个用于信号量,一个用于数据本身。但我本可以创建一个 struct
并将两个变量放入其中,这可能更有意义,因为 mmap
ed 内存必须是页面对齐的,因此我 认为 每个新的内存映射至少需要 1 整页内存。关于如何在进程之间公开您想要的状态,您肯定需要考虑一些事情。
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <errno.h>
#include <unistd.h>
#include <semaphore.h>
#define BUFSIZE 20480
int main(int argc, char**argv){
int protection = PROT_READ | PROT_WRITE;
int visibility = MAP_SHARED | MAP_ANONYMOUS;
// we need shared memory for our semaphore
sem_t* sem = mmap(NULL, sizeof(sem_t), protection, visibility, -1, 0);
if(sem == MAP_FAILED) {
perror("Couldn't create memory map");
exit(errno);
}
if( sem_init(sem, 1, 0) != 0 ){
perror("couldn't init shared memory");
exit(errno);
}
// now shared memory for the data we care about, which is just a string up to BUFSIZE len including termination
void* shmem = mmap(NULL, BUFSIZE, protection, visibility, -1, 0);
if(shmem == MAP_FAILED) {
perror("Couldn't create memory map");
exit(errno);
}
// let's make sure there's a '[=10=]' at the end for the string functions by copying an empty string in.
strncpy(shmem, "" , BUFSIZE-1);
pid_t cpid = fork();
if(cpid < 0){
perror("Couldn't fork");
exit(errno);
}
else if( cpid == 0 ){ // child!
char* msg = malloc(sizeof(char)*BUFSIZE);
*msg = '[=10=]';
while( strlen(msg) == 0 ){
printf("What would you like the message to be? ");
fflush(stdout);
fgets(msg, BUFSIZE, stdin);
}
printf("%lu character string input\n", strlen(msg));
strncpy(shmem, msg, BUFSIZE-1);
sem_post(sem);
}
else {
int sig;
if( sem_wait(sem) ){
perror("couldn't wait for semaphore in parent");
exit(errno);
}
printf("%lu character string input\n", strlen(shmem));
}
}
我正在创建一个使用套接字进行连接的客户端-服务器程序,一旦客户端连接到服务器,就会为客户端创建一个新进程(项目需要)。我在服务器中有一个链接列表,用于存储持有有关它们的信息的客户端结构。
这造成的问题是,例如,当 2 个客户端连接时,每个客户端只能查看其中包含详细信息的链表版本。所以我正在尝试创建一个包含链接列表的共享内存段,但我是共享内存的新手并且正在努力让它工作。
node_t *client_list = NULL;
int main() {
int shmid;
key_t key;
key = 1234;
shmid = shmget(key, SHMSZ, IPC_CREAT | 0666);
client_list = (node_t *) shmat(shmid, (void *)0, 0);
while(1) {
pid_t current_process;
if ((current_process = fork()) == 0) {
node_add(client_list, &client);
node_print(client_list);
pthread_create(&thread[client_count], NULL, network(client.ID), (void *) &client);
}
return 0;
}
(我已将套接字连接代码等关闭以使其更具可读性)。 我可能在当前版本中做错了一些事情,但我的理解是我正在为 'node_t *client_list' 创建共享内存段,这是一个链表,然后在从连接创建新进程后,将客户端节点添加到其中.任何帮助将不胜感激。
对这个问题有点好奇,所以我想把分叉/共享内存和信号量的概念证明放在一起,以防止读取不完整的写入。
我有一些要点:
mmap
似乎是比 sysv 共享内存段更简单、更现代的共享内存实现。- 需要信号量或其他协调来确保读取完成而写入未完成。
mmap
中的数据是共享的,但如果该数据是一个指针,它必须指向一个 mmap 段,否则它不会在每个 fork 中工作......我很确定。因此,请确保将您的共享数据 all 放入共享内存中,而不仅仅是其地址。
关于使用共享内存的注意事项:我创建了 2 个不同的 mmap
-共享内存,一个用于信号量,一个用于数据本身。但我本可以创建一个 struct
并将两个变量放入其中,这可能更有意义,因为 mmap
ed 内存必须是页面对齐的,因此我 认为 每个新的内存映射至少需要 1 整页内存。关于如何在进程之间公开您想要的状态,您肯定需要考虑一些事情。
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <errno.h>
#include <unistd.h>
#include <semaphore.h>
#define BUFSIZE 20480
int main(int argc, char**argv){
int protection = PROT_READ | PROT_WRITE;
int visibility = MAP_SHARED | MAP_ANONYMOUS;
// we need shared memory for our semaphore
sem_t* sem = mmap(NULL, sizeof(sem_t), protection, visibility, -1, 0);
if(sem == MAP_FAILED) {
perror("Couldn't create memory map");
exit(errno);
}
if( sem_init(sem, 1, 0) != 0 ){
perror("couldn't init shared memory");
exit(errno);
}
// now shared memory for the data we care about, which is just a string up to BUFSIZE len including termination
void* shmem = mmap(NULL, BUFSIZE, protection, visibility, -1, 0);
if(shmem == MAP_FAILED) {
perror("Couldn't create memory map");
exit(errno);
}
// let's make sure there's a '[=10=]' at the end for the string functions by copying an empty string in.
strncpy(shmem, "" , BUFSIZE-1);
pid_t cpid = fork();
if(cpid < 0){
perror("Couldn't fork");
exit(errno);
}
else if( cpid == 0 ){ // child!
char* msg = malloc(sizeof(char)*BUFSIZE);
*msg = '[=10=]';
while( strlen(msg) == 0 ){
printf("What would you like the message to be? ");
fflush(stdout);
fgets(msg, BUFSIZE, stdin);
}
printf("%lu character string input\n", strlen(msg));
strncpy(shmem, msg, BUFSIZE-1);
sem_post(sem);
}
else {
int sig;
if( sem_wait(sem) ){
perror("couldn't wait for semaphore in parent");
exit(errno);
}
printf("%lu character string input\n", strlen(shmem));
}
}