Это домашнее задание. Задача состоит в том, чтобы реплицировать команду оболочки: ls | wc -l
в C, используя общую память с mmap()
при соблюдении стандартов POSIX.
Вот мой оригинальный подход к проблеме:
- Создание области общей памяти
sh_mem
- Форк процесса
- Внутри дочернего процесса:
- Привязка
stdout
для записи в sh_mem
каким-либо образом - Позвоните
execlp("ls", "ls", NULL)
- Внутри родительского процесса:
wait(NULL)
для завершения ребенком - Привязка
stdin
для чтения с sh_mem
как-то - Звоните
execlp("wc", "wc", "-l", NULL)
Проблема:
Однако я не мог думать о том, как связать stdin
/ stdout
с sh_mem
. Я сделал это с помощью конвейеров и подумал, что смогу реализовать нечто подобное здесь, но я не смог найти никаких путей.
Можете ли вы дать мне советы, как решить эту проблему?
Код: (не полный)
Вот мой код, который я написал до сих пор, но сейчас он довольно бесполезен. Он просто пишет и читает от ребенка и родителя.
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/wait.h>
#include <sys/mman.h>
#include <string.h>
int main() {
const char* p_msg = "Hello";
const char* c_msg = "World";
void* shmem = mmap(NULL, sysconf(_SC_PAGESIZE), PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);
memcpy(shmem, p_msg, sizeof(p_msg));
int pid = fork();
if(pid == 0){
printf("Child reads: %s\n", shmem);
memcpy(shmem, c_msg, sizeof(c_msg));
}
else {
printf("Parent reads: %s\n", shmem);
sleep(1);
printf("after one sec: %s\n", shmem);
}
}
Возможное решение 1:
Я подумал о другом подходе, где я использую файл для записи и получения карта памяти в файл. Но тогда я не вижу утилиты разделяемой памяти, если файл используется для фактического чтения и записи.
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/wait.h>
#include <sys/mman.h>
#include <string.h>
int main() {
int returnstatus;
// Create a file
int fd = open("shmem.txt", O_RDWR | O_CREAT, O_RDWR);
// Create a memory map of the file
void* sh_mem = mmap(NULL, sysconf(_SC_PAGESIZE), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
// Create a child process int pid = fork();
if(pid == 0){
// Inside Child process
// Link stdout to file
dup2(fd, 1);
// Close unused fd
close(fd)
// Execute ls
execlp("ls", "ls", NULL);
else {
// Inside Parent Process
// Link stdin to file/sh_mem
// Execute wc
}
}
Возможное решение 2:
Предложено @kaylum. Используйте shm_open()
, чтобы получить fd
в общую память.
Я пробовал, но это не работает, как я ожидал. Он не связывает ни stdout
, ни stdin
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/wait.h>
#include <sys/mman.h>
#include <string.h>
int main() {
int returnstatus;
// Get the fd of the map
int fd = open("sh.file", O_RDWR, O_RDWR);
// Create a memory map of the file
void* sh_mem = mmap(NULL, sysconf(_SC_PAGESIZE), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
// Create a child process
int pid = fork();
if(pid == 0){
// Inside Child process
// Link stdout to file
dup2(fd, 1);
// Close unused fd
close(fd);
// Execute ls
execlp("ls", "ls", NULL);
}
else { // Inside Parent Process
// Link stdin to file
dup2(fd, 0);
// CLose unused fd
close(fd);
// Execute wc
execlp("wc", "wc", "-l", NULL);
}
}