如何使用 char 指针写入共享内存?

How do I write to shared memory using a char pointer?

提问人:TheCanadian 提问时间:10/21/2023 更新时间:10/21/2023 访问量:98

问:

#define MIN_PID 300
#define MAX_PID 5000
#define SPROD_NAME "/sem_prod"
#define SCONS_NAME "/sem_cons"

std::vector<int> pidb = {};
int count = 0;

char* pid_manager::produce(pid_manager& task_manager, char *ptr) {
    const char* pid = (std::to_string(task_manager.allocate_pid())).c_str();
    std::cout << "Produced: " << pid << std::endl;
    std::strcpy(ptr, pid);
    ptr += strlen(pid);
    count += strlen(pid);
    std::cout << ptr <<std::endl;
    return ptr;
}

char* pid_manager::consume(pid_manager& task_manager, char *ptr) {
    std::cout << "Consumed: " << std::endl;
    const char* data = ptr;
    std::cout << data << std::endl;
    return ptr;
}

void pid_manager::producer(pid_manager& task_manager) {

    // connecting to shared semaphores
    sem_t *sem_prod = sem_open(SPROD_NAME, 0);
    sem_t *sem_cons = sem_open(SCONS_NAME, 0);

    // shared memory arguments, and creation/configuration of shared memory using mmap
    const int SIZE = 4096;
    const char *name = "OS";
    int fd;
    char *ptr;
    fd = shm_open(name,O_CREAT | O_RDWR,0666);
    ftruncate(fd, SIZE);
    ptr = (char *)mmap(0, SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);

    // creating PID map
    task_manager.allocate_map();

    // signals to consumer to connect to memory
    sem_post(sem_cons);

    sem_wait(sem_prod);
    ptr = task_manager.produce(task_manager, ptr);
    sem_post(sem_cons);
}

void pid_manager::consumer(pid_manager& task_manager) {

    // connecting to shared semaphores
    sem_t *sem_prod = sem_open(SPROD_NAME, O_CREAT, 0644, 1);
    sem_t *sem_cons = sem_open(SCONS_NAME, O_CREAT, 0644, 0);

    // shared memory arguments and mapping consumers ptr to shared memory
    const int SIZE = 4096;
    const char *name = "OS";
    int fd;
    char *ptr;
    fd = shm_open(name, O_RDONLY, 0666);
    ptr = (char *)mmap(0, SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
    std::cout << ptr << std::endl;

    // munmap(ptr,SIZE);
    // close(fd);
    // return;

    // sending signal to producer that consumer is connected to shared memory
    sem_post(sem_prod);

    // waits for memory to be written, then reads the memory
    sem_wait(sem_cons);
    std::cout << "Running consume" << std::endl;
    ptr = task_manager.consume(task_manager, ptr);
    sem_post(sem_prod);


    //remove shared memory
    shm_unlink(name);
}


int main(){
    // initialization of name of process, pid_manager object, and shared memory semaphores
    std::string name;
    pid_manager task_manager;
    sem_t *sem_prod = sem_open(SPROD_NAME, O_CREAT, 0666, 1);
    sem_t *sem_cons = sem_open(SCONS_NAME, O_CREAT, 0666, 0);

    if (fork() == 0) {
        name = "producer";
        sem_t *sem_prod = sem_open(SPROD_NAME, 0);
        sem_t *sem_cons = sem_open(SCONS_NAME, 0);
    }
    else {
        name = "parent";
        if (fork() == 0) {
            name = "consumer";
            sem_t *sem_prod = sem_open(SPROD_NAME, 0);
            sem_t *sem_cons = sem_open(SCONS_NAME, 0);
        }
    }
    
    // sem_unlink(SPROD_NAME);
    // sem_unlink(SCONS_NAME);
    // sem_close(sem_prod);
    // sem_close(sem_cons);
    // return 0;

    // runs producer process if not parent
    if (name == "producer") {
        sem_wait(sem_prod);
        std::cout << "Producer Process Executed" << std::endl;
        task_manager.producer(std::ref(task_manager));
    }

    //runs consumer process if not parent
    if (name == "consumer") {
        sem_wait(sem_cons);
        std::cout << "Consumer Process Executed" << std::endl;
        task_manager.consumer(std::ref(task_manager));
    }

    std::cout << "Parent process here!" << std::endl;
    wait(NULL);
    wait(NULL);
    wait(NULL);
    
    sem_close(sem_prod);
    sem_close(sem_cons);
    return 0;
}


在我的代码中,生产者函数创建共享内存,消费者函数连接到该共享内存,它们通过单个 const char* ptr 访问它。生产者和消费者都调用生产和消费,它们应该进行实际的读取和写入,但两者都冻结在他们写入和读取的行上,没有错误或终止。

所有对 pid 相关内容的调用都只是我们正在构建的项目,它只是一个数组,函数返回它们分配/销毁的数组的索引。 我对共享内存/信号量没有经验,所以我只是通过注释代码并运行它来清除内存,因为我无法让它运行到最后。

我为一大块糟糕的代码道歉,但我真的不知道如何让它工作。

我主要专注于尝试让 produce 函数写入 ptr 指向的内存,因为如果不先运行 produce,consume 甚至无法运行。我老师的例子是:

const char* pid = (std::to_string(task_manager.allocate_pid())).c_str();
sprintf(ptr, "%s", pid);

但我也试过:

const char* pid = (std::to_string(task_manager.allocate_pid())).c_str();
std::strcpy(ptr, pid);
C++ 信号量 共享内存

评论

6赞 Igor Tandetnik 10/21/2023
const char* pid = (std::to_string(task_manager.allocate_pid())).c_str();这将构造一个临时对象,然后获取指向该对象管理的内存块的指针。然后,临时在分号处被销毁,指针变得悬空。随后尝试使用此指针时,会通过在对象生存期结束后访问对象来表现出未定义的行为。std::string

答: 暂无答案