0x00思路

为了给TinyHTTPd源码分析打下基础,先写一个简单父子进程管道通信的样例

1,先定义,并绑定read,write函数和缓冲区,创建pipe管道数组(下标0对于读段,1对应写端,这是强制规定的)

2.父进程fork后,父子进程各有一套1中的变量,且代码执行是同步的,只不过储存空间不在一起,然后对父子进程的管道进行操作使之可以通信

0x01函数

write

#include <unistd.h>
ssize_t write(int fd, const void *buf, size_t count);

将buf所指的内存中的count个字节,写入到文件描述符fd所指的文件中去。

read

number = read(handle, buffer ,n);

上述read调用函数中,各个参数的定义如下:

handle: 这是一个已经打开的文件标识符,表示从这个文件句柄所代表的文件读取数据。

buffer: 指缓冲区,即读取的数据会被放到这个缓冲区中去。

n: 表示调用一次read操作,应该读多少数量的字符。

number:表示系统实际所读取的字符数量。

pipe

头文件: #include<unistd.h>
函数原型:int pipe(int filedes[2]);

函数说明:pipe()会建立管道,并将文件描述词由参数filedes数组返回。

filedes[0]为管道里的读取端

filedes[1]则为管道的写入端。

返回值: 若成功则返回零,否则返回-1,错误原因存于errno中。

错误代码:

EMFILE 进程已用完文件描述词最大量

ENFILE 系统已无文件描述词可用。

EFAULT 参数 filedes 数组地址不合法。

fork

头文件:#include <unistd.h>#include<sys/types.h>
函数原型:pid_t fork( void);

创建一个新的进程。(pid_t 是一个宏定义,其实质是int 被定义在#include<sys/types.h>中)

fork后发生了什么

1.由fork创建的新进程被称为子进程(child process)。该函数被调用一次,但返回两次。两次返回的区别是子进程的返回值是0,

2.而父进程的返回值则是新进程(子进程)的进程 id。将子进程id返回给父进程的理由是:因为一个进程的子进程可以多于一个,没有一个函数使一个进程可以获得其所有子进程的进程id。

3.对子进程来说,之所以fork返回0给它,是因为它随时可以调用getpid()来获取自己的pid;也可以调用getppid()来获取父进程的id。(进程id为0的总是由交换进程使用,所以一个子进程的进程id不可能为0)。

4.fork之后,操作系统会复制一个与父进程完全相同的子进程。虽说是父子关系,但是在操作系统看来,他们更像兄弟关系,这2个进程共享代码空间,但是数据空间是互相独立的,子进程数据空间中的内容是父进程的完整拷贝,指令指针也完全相同,子进程拥有父进程当前运行到的位置(两进程的程序计数器pc值相同。也就是说,子进程是从fork返回处开始执行的)

5.但有一点不同,如果fork成功,子进程中fork的返回值是0,父进程中fork的返回值是子进程的进程号,如果fork不成功,父进程会返回错误。

可以这样想象,2个进程一直同时运行,而且步调一致,在fork之后,他们分别作不同的工作,也就是分岔了。

注意:

fork()函数主要是以父进程为蓝本复制一个进程,其ID号和父进程的ID号不同。对于结果fork出来的子进程的父进程ID号是执行fork()函数的进程的ID号;

例如:

父进程, fork返回值是:17025, ID:17024 ,父进程ID:16879

子进程, fork返回值是:0, ID:17025 ,父进程ID:17024

close

用这个函数来关闭管道的一端

0x02重要变量

1.result异常变量,用来进行判断一些函数的异常返回情况

2.pid进程变量(在fork函数的使用过程中很重要)

3.read/write buffer 在文件读写的时候创建缓冲区i

4.fd[2]pipe读写端数组 实现管道通信

0x03遇到的问题

1.对管道通信pipe读写端在不同进程下是怎样的关系不明确

2.fork函数两个返回值的利用实现父子进程过程不清楚

3.为什么TinyHTTPd要两个管道,而这个简单例子只需要一个管道

0x04解决问题

1.见下图

2.见下图

3.因为这个样例不需要双向通信,子进程并没有反馈给父进程

0x05代码

#include<stdio.h>
#include<stdlib.h>
#include<sys/types.h>
#include<unistd.h>
#include<string.h>int main(void){// pid_t pid;int i=0;int result = -1;int fd[2],nbytes;char string[100];char readbuffer[80];//int *write_fd = &fd[1];//int *read_fd = &fd[0];printf("Please input data:");scanf("%s",string);result = pipe(fd);                  !!!!用fd建立了pip管道链接if(-1 == result){perror("pipe");return -1;}/*pid=fork();                              !!!!!!!父子进程分开if(-1 == pid) //此处为了验证父子进程是否创建成功,如果未创建成功,则返回-1{perror("fork");return -1;}else if(0 == pid)//如果是子进程{printf(“this is child %d\n”, getpid());close(*read_fd);//关掉子进程的读端,只剩下写端result = write(*write_fd,string,strlen(string));//向string写入,写入到文件描述符pipe写端return 0;}*/else//如果不是子进程{printf(“this is parent %d\n”, getpid());close(*write_fd);//关闭父进程的pip写端,只留下读端nbytes = read(*read_fd,readbuffer,sizeof(readbuffer)-1);//从read_fd中读入,先放入readbufferprintf("receive %d data:%s\n",nbytes,readbuffer);}
return 0;
}

父子进程管道通信(附简单样例)相关推荐

  1. 已知一个掺杂了多个数字字符的中文名拼音,去掉所有数字字符之后,形式为“名”+空格+“姓”;并且名和姓的首字母大写,其他小写,要求输出姓名全拼,且全为小写。(后附详细样例说明)

    已知一个掺杂了多个数字字符的中文名拼音,去掉所有数字字符之后,形式为"名"+空格+"姓":并且名和姓的首字母大写,其他小写,要求输出姓名全拼,且全为小写.(后附 ...

  2. JDBC 连接Hive 简单样例(开启Kerberos)

    今天在移动的云平台上通过jdbc连接hive,发现云平台使用了 kerberos的认证.与宁波实验环境不同. 发现一文解决了问题,转载如下: 原文地址:http://blog.csdn.net/zen ...

  3. 重要性采样(Importance Sampling)简介和简单样例实现

    重要性采样(Importance Sampling)简介和简单样例实现 在渲染领域,重要性采样这个术语是很常见的,但它究竟是什么呢?我们首先考虑这样的一种情况: 如果场景里有一点P,我们想计算P点的最 ...

  4. C语言单元测试之安装gtest教程及一个简单样例

    准备工作 安装包:gtest1.7.0版本(最新的1.8.0版本一直安装失败,1.7.0版本一次成功) 安装链接:百度网盘 https://pan.baidu.com/s/1mDy9sB3sBIMei ...

  5. K8S Yaml 详细说明及简单样例

    一.K8S Yaml 配置文件主要分为基本标签.元数据标签.资源内容 3 个部分 基本标签 apiVersion: v1 #必选,版本号,例如v1 kind: Pod #必选,Pod 元数据标签 me ...

  6. NASBench101-安装及简单样例使用指南

    NASBench101-安装及简单样例使用指南 github地址:https://github.com/google-research/nasbench paper原文地址:https://arxiv ...

  7. java 泛型向下转型_Java向上转型和向下转型(附具体样例)

    Java向上转型和向下转型(附具体样例) 熬夜整理的关于Java向上和向下转型的样例,很的通俗易懂哦~~~~ 一.向上转型 package com.sheepmu; class Animal { pu ...

  8. Argo Workflow简单样例——dag-阿里云开发者社区

    什么是Argo Workflow Argo Workflow是一个开源项目,为Kubernetes提供Container-native工作流程,主要通过Kubernetes CRD实现.它有四大特点: ...

  9. linux进程管道通信缺点,Linux进程通信(IPC)的方式详解

    前言:Linux进程通信的方式 什么是进程通信?进程通信是指进程之间交换信息 进程通信方式共有6种: 管道(pipe),包括流管道(s_pipe)和有名管道(named pipe) 信号(signal ...

最新文章

  1. Activity如何后台运行?不是缓存,是运行。
  2. linux遍历文件夹下所有文件大小,Linux系统遍历文件夹 获取文件大小的操作(C语言实现)...
  3. 全面布局大数据平台,银科控股签约神策数据
  4. 一般屏幕的3D模型是公开的吗?
  5. 腾讯课堂的物理实验(2017计蒜客初赛第三场)
  6. Android `AsyncTask`简要分析
  7. 用于科研的移动机器人平台推荐
  8. python 常用模块函数_python函数和常用模块(三),Day5
  9. java html写入到word文档_java 使用jacob将html页面写入word
  10. linux睡眠进程,linux一个进程如何睡眠
  11. 2017-2018-1 20155308 《信息安全系统设计基础》课堂第六章测试(补做)
  12. 对bmp文件内存压缩 与 解压缩
  13. java继承中的初始化顺序
  14. 高通芯片中的MDP模块[msm7x27]
  15. Spring事件监听Demo
  16. win10和深度linux双系统,深度系统(deepin)与win10双系统切换设置
  17. 犀牛建立html格式,犀牛基础操作图文教程,教你rhino如何导出cad文件格式
  18. Eclipse设置、调优、使用
  19. 【IDEA】解决: alt+/快捷键 冲突的问题
  20. 反向代理分离资源服务器分析

热门文章

  1. web前端 品优购首页+源代码(2)
  2. python头像教程_用Python给头像加上圣诞帽,新手必学
  3. java gitblit_Gitblit 服务器搭建
  4. webuploader常用知识及方法、网站
  5. 网易大数据面试题答案
  6. linux sipp 呼叫转移_开源VoIP/电话 - linux学习笔记 - CSDN博客
  7. 后台服务器开发学习指南(建议收藏)
  8. H5APP中监听返回事件处理
  9. LinqC#3.0 Hands on Lab
  10. Qt中低功耗蓝牙模块使用