日期:2014-05-16  浏览次数:20678 次

Linux/UNIX进程间的通信(1)

进程间的通信(1)

进程间的通信IPC(InterProcessCommunication )主要有以下不同形式:

半双工管道和FIFO;全双工管道和命名全双工管道;消息队列,信号量和共享存储;套接字和STREAMS

管道

pipe函数

当从一个进程连接到另一个进程时,我们使用术语管道。我们通常是把一个进程的输出通过管道连接到另一个进程的输入。

管道是由调用pipe函数创建的:

#include<unistd.h>

int pipe(intpipefd[2]);

经由参数pipefd返回两个文件描述符:pipefd[0]为读而打开,pipefd [1]为而打开。pipefd [1]的输出是pipefd [0]的输入。特别要要注意,这里使用的是文件描述符而不是文件流,所有我们必须用底层的read和write调用来访问,而不能用fread和fwrite。

单个进程中的管道几乎没有任何用处。通常,调用pipe的进程接着调用fork,这样就创建了从父进程子进程的IPC通道。调用fork后,对于从父进程到子进程的管道,父进程关闭管道的读端pipefd [0],子进程则关闭写端pipefd [1];对于从子进程到父进程的管道,父进程关闭pipefd [1],子进程关闭pipefd [0]。以下程序说明其用法:

#include<unistd.h>
#include<stdlib.h>
#include<stdio.h>
#include<string.h>
 
#define BUFSIZE1024
int main()
{
    int data_processed;
    int file_pipes[2];
    const char some_data[] = "123";
    char buffer[BUFSIZE + 1];
    pid_t fork_result;
 
    memset(buffer,'\0', sizeof(buffer));
 
    if(pipe(file_pipes) == 0)
    {
        fork_result = fork();
        if(fork_result == -1)
        {
            fprintf(stderr, "Forkfailure");
exit(EXIT_FAILURE);
        }
 
        if(fork_result == 0)
        {
                            close(file_pipes[1]);
            data_processed =read(file_pipes[0],buffer,BUFSIZE);
            printf("Read %d bytes: %s\n", data_processed, buffer);
            exit(EXIT_SUCCESS);
        }
        else
        {
close(file_pipes[0]);
            data_processed =write(file_pipes[1], some_data,
                    strlen(some_data));
            printf("Wrote %dbytes\n",data_processed);
        }
 
    }


执行结果如下所示:

Wrote 3 bytes

Read 3 bytes:123

 

在下面例子中,展示了如何在子进程中运行一个与其父进程完全不同的另外一个程序,而不是仅仅运行一个相同的程序,我们用exec调用来完成这一工作。由于调用exec后,子进程内存和父进程不同,所以为了访问创建管道后的文件描述符,需要将文件描述符作为一个参数传递给exec启动程序。

第一个程序是数据生产者,负责创建管道和启动子进程

#include<unistd.h>
#include<stdlib.h>
#include<stdio.h>
#include<string.h>
 
#define BUFSIZE1024
int main()
{
    int data_processed;
    int file_pipes[2];
    const char some_data[] = "123";
    char buffer[BUFSIZE + 1];
    pid_t fork_result;
 
    memset(buffer,'\0', sizeof(buffer));
 
    if(pipe(file_pipes) == 0)
    {
        fork_result = fork();
        if(fork_result == -1)
        {
            fprintf(stderr, "Forkfailure");
exit(EXIT_FAILURE);
        }
 
        if(fork_result == 0)
        {
close(file_pipes[1]);
            sprintf(buffer, "%d",file_pipes[0]);
           (void)execl("pipe2","pipe2",buffer,(char*)0);
            exit(EXIT_FAILURE);
        }
        else
        {
close(file_pipes[0]);
            data_processed = write(file_pipes[1],some_data,
                    strlen(some_data));
            printf("%d - WROTE %dBYTES\n",getpid(),data_processed);
        }
 
    }
    exit(EXIT_SUCCESS);
}