Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/linux/27.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Linux IPC-如何将命令输出重定向到子系统中的共享内存段_Linux_Ipc - Fatal编程技术网

Linux IPC-如何将命令输出重定向到子系统中的共享内存段

Linux IPC-如何将命令输出重定向到子系统中的共享内存段,linux,ipc,Linux,Ipc,我试图将Unix命令输出重定向(写入)到子系统中的共享内存段, 然后让父进程从父进程中的同一共享内存段读回输出。在几次徒劳的尝试之后,我没有取得多少成功。谁能给我指路吗? 提前谢谢 我的代码: #包括 #包括 #包括 #包括 #定义SHM_大小1024 int main() { key\u t key;int shmid;char*数据; pid_t cpid=fork(); 若有(消费物价指数) 出于测试目的,我建议您阅读stdin,然后将它们写入数据中 下面是一个使用POSIX共享内存的示

我试图将Unix命令输出重定向(写入)到子系统中的共享内存段, 然后让父进程从父进程中的同一共享内存段读回输出。在几次徒劳的尝试之后,我没有取得多少成功。谁能给我指路吗? 提前谢谢

我的代码:
#包括
#包括
#包括
#包括
#定义SHM_大小1024
int main()
{
key\u t key;int shmid;char*数据;
pid_t cpid=fork();
若有(消费物价指数)
出于测试目的,我建议您阅读
stdin
,然后将它们写入
数据中


下面是一个使用POSIX共享内存的示例(POSIX IPC API优于SYSV IPC API),其中子级从
stdin
读取共享内存区域,父级将此共享内存区域的内容写入
stdout

#include <sys/types.h>
#include <sys/mman.h>
#include <sys/stat.h>

#include <unistd.h>
#include <fcntl.h>
#include <semaphore.h>

#include <stdio.h>
#include <stdlib.h>

int
main(int argc, char *argv[])
{
    const char *shm_name = "/dummy_cat_shm";
    int shm_fd;
    off_t shm_length;

    const char *read_sem_name = "/dummy_cat_read";
    const char *write_sem_name = "/dummy_cat_write";

    sem_t *read_sem, *write_sem;
    pid_t pid;
    int buf_length;
    char *write_ptr, *read_ptr;

    buf_length = 1024;
    shm_length = sizeof(buf_length) + buf_length;

    /* Create semaphore */
    read_sem = sem_open(read_sem_name, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR, 0);
    if (read_sem == SEM_FAILED) {
        perror("sem_open");
        goto clean_up3;
    }
    write_sem = sem_open(write_sem_name, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR, 1);
    if (write_sem == SEM_FAILED) {
        perror("sem_open");
        goto clean_up2;
    }

    /* Create shared memory segment */
    shm_fd = shm_open(shm_name, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
    if (shm_fd < 0) {
        perror("shm_open");
        goto clean_up1;
    }

    if (ftruncate(shm_fd, shm_length) < 0) {
        perror("ftruncate");
        goto clean_up0;
    }

    if ((pid = fork()) < 0) {
        perror("fork");
        goto clean_up0;
    }
    else if (pid == 0) {
        write_ptr = mmap(NULL, shm_length, PROT_WRITE, MAP_SHARED, shm_fd, 0);
        if (write_ptr == MAP_FAILED) {
            perror("mmap");
            goto clean_up0;
        }

        char *buf = write_ptr+sizeof(buf_length);

        while (sem_wait(write_sem) == 0) {
            if (fgets(buf, buf_length, stdin) != NULL) {
                *(int *)write_ptr = 1;
                sem_post(read_sem);
            }
            else {
                *(int *)write_ptr = 0;
                sem_post(read_sem);
                break;
            }
        }

        munmap(write_ptr, shm_length);
    }
    else {
        read_ptr = mmap(NULL, shm_length, PROT_READ, MAP_SHARED, shm_fd, 0);
        if (read_ptr == MAP_FAILED) {
            perror("mmap");
            goto clean_up0;
        }

        char *buf = read_ptr + sizeof(buf_length);

        while (sem_wait(read_sem) == 0) {
            if (*(int *)read_ptr > 0) {
                printf("%s", buf);
                sem_post(write_sem);
            }
            else {
                break;
            }
        }

        munmap(read_ptr, shm_length);
    }

clean_up0:
    shm_unlink(shm_name);

clean_up1:
    sem_unlink(write_sem_name);

clean_up2:
    sem_unlink(read_sem_name);

clean_up3:
    exit(EXIT_FAILURE);
}
运行:

$ ls / | ./a.out 
bin/   home/        lib32/       mnt/   run/      sys/  vmlinuz@
boot/  initrd.img@  lib64/       opt/   sbin/     tmp/  vmlinuz.old@
dev/   initrd.img.old@  lost+found/  proc/  selinux/  usr@
etc/   lib/     media/       root/  srv/      var/
出于测试目的,我建议您阅读
stdin
,然后将它们写入
数据中


下面是一个使用POSIX共享内存的示例(POSIX IPC API优于SYSV IPC API),其中子级从
stdin
读取共享内存区域,父级将此共享内存区域的内容写入
stdout

#include <sys/types.h>
#include <sys/mman.h>
#include <sys/stat.h>

#include <unistd.h>
#include <fcntl.h>
#include <semaphore.h>

#include <stdio.h>
#include <stdlib.h>

int
main(int argc, char *argv[])
{
    const char *shm_name = "/dummy_cat_shm";
    int shm_fd;
    off_t shm_length;

    const char *read_sem_name = "/dummy_cat_read";
    const char *write_sem_name = "/dummy_cat_write";

    sem_t *read_sem, *write_sem;
    pid_t pid;
    int buf_length;
    char *write_ptr, *read_ptr;

    buf_length = 1024;
    shm_length = sizeof(buf_length) + buf_length;

    /* Create semaphore */
    read_sem = sem_open(read_sem_name, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR, 0);
    if (read_sem == SEM_FAILED) {
        perror("sem_open");
        goto clean_up3;
    }
    write_sem = sem_open(write_sem_name, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR, 1);
    if (write_sem == SEM_FAILED) {
        perror("sem_open");
        goto clean_up2;
    }

    /* Create shared memory segment */
    shm_fd = shm_open(shm_name, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
    if (shm_fd < 0) {
        perror("shm_open");
        goto clean_up1;
    }

    if (ftruncate(shm_fd, shm_length) < 0) {
        perror("ftruncate");
        goto clean_up0;
    }

    if ((pid = fork()) < 0) {
        perror("fork");
        goto clean_up0;
    }
    else if (pid == 0) {
        write_ptr = mmap(NULL, shm_length, PROT_WRITE, MAP_SHARED, shm_fd, 0);
        if (write_ptr == MAP_FAILED) {
            perror("mmap");
            goto clean_up0;
        }

        char *buf = write_ptr+sizeof(buf_length);

        while (sem_wait(write_sem) == 0) {
            if (fgets(buf, buf_length, stdin) != NULL) {
                *(int *)write_ptr = 1;
                sem_post(read_sem);
            }
            else {
                *(int *)write_ptr = 0;
                sem_post(read_sem);
                break;
            }
        }

        munmap(write_ptr, shm_length);
    }
    else {
        read_ptr = mmap(NULL, shm_length, PROT_READ, MAP_SHARED, shm_fd, 0);
        if (read_ptr == MAP_FAILED) {
            perror("mmap");
            goto clean_up0;
        }

        char *buf = read_ptr + sizeof(buf_length);

        while (sem_wait(read_sem) == 0) {
            if (*(int *)read_ptr > 0) {
                printf("%s", buf);
                sem_post(write_sem);
            }
            else {
                break;
            }
        }

        munmap(read_ptr, shm_length);
    }

clean_up0:
    shm_unlink(shm_name);

clean_up1:
    sem_unlink(write_sem_name);

clean_up2:
    sem_unlink(read_sem_name);

clean_up3:
    exit(EXIT_FAILURE);
}
运行:

$ ls / | ./a.out 
bin/   home/        lib32/       mnt/   run/      sys/  vmlinuz@
boot/  initrd.img@  lib64/       opt/   sbin/     tmp/  vmlinuz.old@
dev/   initrd.img.old@  lost+found/  proc/  selinux/  usr@
etc/   lib/     media/       root/  srv/      var/

如何重定向ls-l的stdout

我们必须对这段代码中涉及的过程(父级和子级)有更多的了解。 您的程序在运行期间创建了多少个进程? 正确答案是三个。 两个进程是父进程和显式分叉子进程。 第三个是由系统(“ls-l”)调用创建的。 此函数隐式派生另一个进程,该进程通过调用exec系列函数执行“ls-l”sell命令。您需要重定向的是由system()函数创建的子进程的输出。这很遗憾,但是system()不在参与者之间建立IPC。如果需要操作输出,请不要使用system()

我同意@leeduhem,popen()可能是最好的方法。 它的工作原理与系统()完全相同,即派生一个新进程并执行“ls-l”。 此外,它还在参与者之间建立了管道IPC,因此很容易捕获子输出并处理它:

char buff[1024];
FILE *fd;

// instead of system("ls -l")
fd = popen("ls -l", "r");
// check for errors

while(fgets(buff, sizeof(buff), fd) != NULL)
{
  // write to the shared memory
}
 
pclose(fd); 
如果不想使用popen()函数,可以编写类似的函数。 一般做法是

  • 打开一个管道()
  • fork()新流程
  • 使用dup2重定向标准输出
  • 调用执行“ls-l”的合适的exec()函数(可能是execl()
  • 从dup2复制的描述符中读取

  • 如何重定向ls-l的stdout

    我们必须对这段代码中涉及的过程(父级和子级)有更多的了解。 您的程序在运行期间创建了多少个进程? 正确答案是三个。 两个进程是父进程和显式分叉子进程。 第三个是由系统(“ls-l”)调用创建的。 此函数隐式派生另一个进程,该进程通过调用exec系列函数执行“ls-l”sell命令。您需要重定向的是由system()函数创建的子进程的输出。这很遗憾,但是system()不在参与者之间建立IPC。如果需要操作输出,请不要使用system()

    我同意@leeduhem,popen()可能是最好的方法。 它的工作原理与系统()完全相同,即派生一个新进程并执行“ls-l”。 此外,它还在参与者之间建立了管道IPC,因此很容易捕获子输出并处理它:

    char buff[1024];
    FILE *fd;
    
    // instead of system("ls -l")
    fd = popen("ls -l", "r");
    // check for errors
    
    while(fgets(buff, sizeof(buff), fd) != NULL)
    {
      // write to the shared memory
    }
     
    pclose(fd); 
    
    如果不想使用popen()函数,可以编写类似的函数。 一般做法是

  • 打开一个管道()
  • fork()新流程
  • 使用dup2重定向标准输出
  • 调用执行“ls-l”的合适的exec()函数(可能是execl()
  • 从dup2复制的描述符中读取

  • 为什么不使用管道让父进程读取子进程的输出?我想学习/练习的练习是共享内存段。我想知道,将其管道化到文件描述符,然后再次将其从fd重新定向到共享内存缓冲区,是否可以完成这项工作。这听起来是多余的,不确定。如果使用管道,共享内存是不必要的ry.这是一种更简单、更正常的方法。为什么不为父进程使用管道来读取子进程的输出?我想学习/练习的练习是共享内存段。我想知道,将其管道化到文件描述符,然后再次将其从fd重新定向到共享内存缓冲区,是否可以完成这项工作。这听起来是多余的,n当然可以。如果你使用管道,共享内存是不必要的。这是一个更容易和正常的方式来做到这一点。