linux程序设计——父进程和子进程(第十三章)

13.5    父进程和子进程

这节将介绍如何在子进程中运行一个与父进程完全不同的另外一个程序,而不是仅仅运行一个相同程序.使用exec调用来完成这一项工作.这里的一个难点是,通过exec调用的进程需要知道应该访问哪个文件描述符.在前面的例子中,因为子进程本身有file_pipes数据的一份副本(点击打开"fork复制进程映像"链接),所以这并不成为问题.但经过exec调用后,情况就不一样了,因为原来的进程已经被新的进程替换了.为解决这个问题,可以将文件描述符(实际上它只是一个数字)作为一个参数传递给用exec启动的程序.

为了演示它是如何工作的,需要使用两个程序.第一个程序是数据生产者,它负责创建管道和启用子进程,而后者是数据消费者.

编写程序pipe3,c,它是从pipe2.c修改而来,实现在两个完全不同的进程之间传递数据

/*************************************************************************
 > File Name:    pipe3.c
 > Description:  pipe3.c程序在两个完全不同的进程之间传递数据
 > Author:       Liubingbing
 > Created Time: 2015年07月11日 星期六 22时28分14秒
 > Other:        pipe3.c程序为了实现<strong>在两个完全不同的进程之间传递数据</strong>,它先创建一个管道,接着使用fork函数在父进程中创建一个子进程,然后在子进程中调用execl函数使用新进程替换子进程.
 ************************************************************************/

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

int main()
{
	int data_processed;
	int file_pipes[2];
	const char some_data[] = "123";
	char buffer[BUFSIZ + 1];
	pid_t fork_result;

	memset(buffer, '\0', sizeof(buffer));

	if (pipe(file_pipes) == 0) {
		fork_result = fork();
		if (fork_result == (pid_t) - 1) {
			fprintf(stderr, "Fork failure");
			exit(EXIT_FAILURE);
		}

		if (fork_result == 0) {
			/* sprintf函数将格式化的file_pipe[0]数据写入到buffer指向的内存 */
			sprintf(buffer, "%d", file_pipes[0]);
			/* execl函数把当前进程替换为一个新进程,新进程由path或file参数指定. 此时,将父进程fork调用之后创建的子进程替换为指定的新进程pipe4
			 * 第一个参数"pipe4"为要启动的程序
			 * 第二个参数"pipe4"为程序名
			 * 第三个参数buffer包含让被调用程序(即pipe4)去读取的文件描述符(即file_pipe[0])
			 * 第四个参数(char *)0的作用是终止被调用程序的参数列表 */
			(void)execl("pipe4", "pipe4", buffer, (char *)0);
			exit(EXIT_FAILURE);
		} else {
			/* write函数从some_data指向的内存中写入stlen(some_data)个字节的数据到file_pipes[1]指向的文件中 */
			data_processed = write(file_pipes[1], some_data, strlen(some_data));
			printf("%d - wrote %d bytes\n", getpid(), data_processed);
		}
	}
	exit(EXIT_SUCCESS);
}

接下来编写程序pipe4.c,它将被pipe3.c调用.

/*************************************************************************
 > File Name:    pipe4.c
 > Description:  pipe4.c程序从参数字符串中提取处文件描述符数字,然后读取文件描述符来获取数据
 > Author:       Liubingbing
 > Created Time: 2015年07月11日 星期六 22时34分05秒
 > Other:        pipe4.c
 ************************************************************************/

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

int main(int argc, char *argv[])
{
	int data_processed;
	char buffer[BUFSIZ + 1];
	int file_descriptor;

	memset(buffer, '\0', sizeof(buffer));
	/* sscanf函数从argv[1]中读取数据,按照"%d"的格式写入到file_descriptor里 */
	sscanf(argv[1], "%d", &file_descriptor);
	/* read函数从file_descriptor指向的文件中读取BUFSIZ个字节的数据到buffer指向的内存中 */
	data_processed = read(file_descriptor, buffer, BUFSIZ);

	printf("%d - read %d bytes: %s\n", getpid(), data_processed, buffer);
	exit(EXIT_SUCCESS);
}

运行pipe3时,将看到如下所示的输出结果:

pipe程序与之前的一样,用pipe函数创建一个管道,然后用fork调用创建一个新进程.接下来,它用sprintf把读取管道数据的文件描述符保存到一个缓存区中,该缓存区的内存将构成pipe4程序的一个参数.

int execlp(const char *file, const char *arg0, ..., (char *)0);  

通过execl调用(在这里点击打开"替换进程映像"的链接查看execl函数)来启动pipe4程序,execl的参数如下所示:

要调用的程序

argv[0]:程序名

argv[1]:包含想让被调用程序去读取的文件描述符

(char *)0:这个参数的作用是终止被调用程序的参数列表

pipe4程序从参数字符中提取出文件描述符数字,然后读取该文件描述符来获取数据.

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2025-01-01 21:40:03

linux程序设计——父进程和子进程(第十三章)的相关文章

linux的父进程向子进程发kill信号例子以及对子进程的状态进行判断

先看一个父进程向子进程发kill信号例子: #include <stdio.h> #include <unistd.h> #include <signal.h> #include <sys/types.h> #include <sys/wait.h> int main(int argc, const char *argv[]) { pid_t pid; int status; pid = fork(); if (0 == pid) { print

linux程序设计——如何实现popen(第十三章)

13.3.2    如何实现popen 请求popen调用运行一个程序时,它首先启动shell,即系统中的sh命令,然后将command字符串作为一个参数传递给它,这有两个效果,一个好,一个不好. 在linux中,所有的参数扩展都是由shell来完成的.所以,在启动程序之前先启动shell来分析命令字符串,就可以使各种shell扩展(如*.c所指的是哪些文件)在程序启动之前就全部完成.这个功能非常有用,它允许通过popen启动非常复杂的shell命令.而其他一些创建进程的函数(如execl)调用

Linux下利用fork()创建子进程并使父进程等待子进程结束

int status; pid_t t = fork(); if(t){ waitpid(t, &status, 0); }else{ system("vi temp.txt"); exit(0); } //父进程和子进程均执行完毕后继续执行下去 分析过程: if 和 else 还是选择分支. 主要的原因是,fork() 函数调用一次,返回两次.两次返回的区别是:子进程的返回值是0,父进程返回值为新子进程的进程ID.返回后,父进程执行waitpid(t, &status

2)Linux程序设计入门--进程介绍

2)Linux程序设计入门--进程介绍 Linux下进程的创建 前言: 这篇文章是用来介绍在Linux下和进程相关的各个概念.我们将会学到: 进程的概念 进程的身份 进程的创建 守护进程的创建 1.进程的概念 Linux操作系统是面向多用户的.在同一时间可以有许多用户向操作系统发出各种命 令.那么操作系统是怎么实现多用户的环境呢? 在现代的操作系统里面,都有程序和进程 的概念.那么什么是程序,什么是进程呢? 通俗的讲程序是一个包含可以执行代码的文件 ,是一个静态的文件.而进程是一个开始执行但是还

关于父进程和子进程的关系(UAC 绕过思路)

表面上看,在windows中.如果是a进程创建了b进程,那么a进程就是b进程的父进程,反之,如果是b创建了a,那么b进程就是a的父进程,这是在windows出现以来一直是程序猿们都证实的,但是在在win Vista后面有了一个新安全消息机制,UAC(user account control),这里科普下UAC的功能,其实UAC就是大家常见的安装软件或者启动程序的时候的出现的全屏变暗的一个提示框,这里顺便提醒下大家不要把它的提醒级别降低,这里大家不要蓄意把他的提示级别较低,这样会带来很大的安全隐患

linux程序设计——多客户(第十五章)

15.4    多客户 到目前为止,本章一直介绍的是,如果用套接字来实现本地的和跨网络的客户/服务器系统.一旦连接建立,套接字连接的行为就类似于打开的底层文件描述符,而且在很多方面类似于双向管道. 现在考虑有多个客户同时连接一个服务器的情况.服务器程序在接受来自客户的一个新连接时,会创建出一个新的套接字,而原先的监听套接字将被保留以继续监听以后的连接.如果服务器不能立刻接受后来的连接,它们将被放到队列中以等待处理. 原先的套接字仍然可用并且套接字的行为就像文件描述符,这一事实提供了一种同时服务多

UNIX网络编程卷1 服务器程序设计范式5 预先派生子进程,由父进程向子进程传递套接字描述符

本文为senlie原创,转载请保留此地址:http://blog.csdn.net/zhengsenlie 1.只让你进程调用 accept,然后把所接受的已连接套接字"传递"给某个子进程. 这样做就不用因为所有子进程都调用 accept 而需提供上锁保护 2.父进程必须跟踪子进程的忙闲状态,以便给空闲子进程传递新的套接字 typedef struct { pid_t child_pid; /* 子进程的进程 ID */ int child_pipefd; /* 父进程中连接到该子进程

父进程和子进程

父进程 在计算机领域,父进程(英语:Parent Process)指已创建一个或多个子进程的进程. UNIX 在UNIX里,除了进程0(即PID=0的交换进程,Swapper Process)以外的所有进程都是由其他进程使用系统调用fork创建的,这里调用fork创建新进程的进程即为父进程,而相对应的为其创建出的进程则为子进程,因而除了进程0以外的进程都只有一个父进程,但一个进程可以有多个子进程. 操作系统内核以进程标识符(Process Identifier,即PID)来识别进程.进程0是系统

父进程与子进程的关系(31-04)

一个父进程(主进程)可以生成多个子进程, 每个父进程/子进程都有一个特定的ID号. from multiprocessing import Process import timeimport os def info(title): print(title) print('module name:', __name__) print('parent process:', os.getppid()) # 显示父进程ID print('process id:', os.getpid()) # 显示子进