从进程开始,搜索和理解进程

Google 搜索关键词: C fork example

什么是fork

Fork系统调用用于创建一个称为子进程的新进程,该子进程与进行fork()调用的进程(父进程)同时运行。

创建新的子进程后,两个进程都将在fork()系统调用之后执行下一条指令。

子进程使用与父进程相同的pc(程序计数器),相同的CPU寄存器,相同的打开文件。

fork返回值

它不带任何参数,并返回一个整数值。以下是fork()返回的不同值。

负值:创建子进程失败。

零:返回到新创建的子进程。

正值:返回给父级或调用者。该值包含新创建的子进程的进程ID。

写点代码

光看上面的解释有点干,来份代码

  1. #include <stdio.h>
  2. #include <sys/types.h>
  3. #include <unistd.h>
  4. int main()
  5. {
  6.  
  7. // make two process which run same
  8. // program after this instruction
  9. fork();
  10.  
  11. printf("Hello world!\n");
  12. return ;
  13. }

输出:

  1. Hello world!
  2. Hello world!

执行fork函数后,父进程和子进程都会执行下一行代码和后面的代码,所以会输出两遍

计算hello打印的次数

  1. #include <stdio.h>
  2. #include <sys/types.h>
  3. int main()
  4. {
  5. fork();
  6. fork();
  7. fork();
  8. printf("hello\n");
  9. return ;
  10. }

输出

  1. hello
  2. hello
  3. hello
  4. hello
  5. hello
  6. hello
  7. hello
  8. hello

hello打印的次数等于创建的进程数。

进程总数= 2^n,其中n是fork系统调用的数目。所以这里n = 3,2^3 = 8

还不理解?我们来逐行分析

  1. fork (); // Line 1
  2. fork (); // Line 2
  3. fork (); // Line 3
  4.  
  5. L1 // There will be 1 child process
  6. / \ // created by line 1.
  7. L2 L2 // There will be 2 child processes
  8. / \ / \ // created by line 2
  9. L3 L3 L3 L3 // There will be 4 child processes
  10. // created by line 3

因此,总共有八个进程(新的子进程和一个原始进程)。

如果我们想将流程之间的关系表示为树层次结构,则如下所示:

主进程:P0

第一个fork函数创建的进程:P1

第二个fork函数创建的进程:P2、P3

第三个fork函数创建的进程:P4、P5、P6、P7

预测以下程序的输出

  1. #include <stdio.h>
  2. #include <sys/types.h>
  3. #include <unistd.h>
  4. void forkexample()
  5. {
  6. // child process because return value zero
  7. if (fork() == )
  8. printf("Hello from Child!\n");
  9.  
  10. // parent process because return value non-zero.
  11. else
  12. printf("Hello from Parent!\n");
  13. }
  14. int main()
  15. {
  16. forkexample();
  17. return ;
  18. }

输出:

  1. .
  2. Hello from Child!
  3. Hello from Parent!
  4. (or)
  5. .
  6. Hello from Parent!
  7. Hello from Child!

在上面的代码中,创建了一个子进程,fork()在该子进程中返回0,并向父进程返回正整数。

在这里,两个输出都是可能的,因为父进程和子进程正在同时运行。 因此,我们不知道操作系统是首先控制父进程还是子进程。

父进程和子进程正在运行同一程序,但这并不意味着它们是相同的。 OS为这两个进程分配不同的数据和状态,并且控制这些进程的流可以有所不同。

看下面的例子:

  1. #include <stdio.h>
  2. #include <sys/types.h>
  3. #include <unistd.h>
  4.  
  5. void forkexample()
  6. {
  7. int x = ;
  8.  
  9. if (fork() == )
  10. printf("Child has x = %d\n", ++x);
  11. else
  12. printf("Parent has x = %d\n", --x);
  13. }
  14. int main()
  15. {
  16. forkexample();
  17. return ;
  18. }

输出:

  1. Parent has x =
  2. Child has x =
  3. (or)
  4. Child has x =
  5. Parent has x =

这里,一个进程中的全局变量更改不会影响其他两个进程,因为两个进程的数据/状态不同。而且父级和子级同时运行,因此有两个输出是可能的。

参考阅读:

1、https://www.geeksforgeeks.org/fork-system-call/

Golang协程实现流量统计系统(2)的更多相关文章

  1. Golang协程实现流量统计系统(3)

    进程.线程.协程 - 进程:太重 - 线程:上下文切换开销太大 - 协程:轻量级的线程,简洁的并发模式 Golang协程:goroutine Hello world package main impo ...

  2. Golang协程实现流量统计系统(1)

    # 学习内容: # 学习目标: 学习Golang的基础开发 常用的Golang编程技艺 精巧省力的Go Lib 协程的真实应用实践 与其他语言对比着学 协程并发模型的深度应用 Growth hacki ...

  3. golang协程同步的几种方法

    目录 golang协程同步的几种方法 协程概念简要理解 为什么要做同步 协程的几种同步方法 Mutex channel WaitGroup golang协程同步的几种方法 本文简要介绍下go中协程的几 ...

  4. Python与Golang协程异同

    背景知识 这里先给出一些常用的知识点简要说明,以便理解后面的文章内容. 进程的定义: 进程,是计算机中已运行程序的实体.程序本身只是指令.数据及其组织形式的描述,进程才是程序的真正运行实例. 线程的定 ...

  5. 面试必问:Golang高阶-Golang协程实现原理

    引言 实现并发编程有进程,线程,IO多路复用的方式.(并发和并行我们这里不区分,如果CPU是多核的,可能在多个核同时进行,我们叫并行,如果是单核,需要排队切换,我们叫并发) 进程和线程的区别 进程是计 ...

  6. 网站流量统计系统 phpMyVisites

    phpMyVisites是一个网站流量统计系统,它能够提供非常详细的统计报告和高级图形报表.phpMyVisites不是一个Apache log分析工具,它建有自己的log.它的特点包括: 安装部署: ...

  7. Golang 协程调度

    一.线程模型 N:1模型,N个用户空间线程在1个内核空间线程上运行.优势是上下文切换非常快但是无法利用多核系统的优点. 1:1模型,1个内核空间线程运行一个用户空间线程.这种充分利用了多核系统的优势但 ...

  8. Golang协程与通道整理

    协程goroutine        不由OS调度,而是用户层自行释放CPU,从而在执行体之间切换.Go在底层进行协助实现      涉及系统调用的地方由Go标准库协助释放CPU      总之,不通 ...

  9. 关于协程:nodejs和golang协程的不同

    nodejs和golang都是支持协程的,从表现上来看,nodejs对于协程的支持在于async/await,golang对协程的支持在于goroutine.关于协程的话题,简单来说,可以看作是非抢占 ...

随机推荐

  1. Mysql学习(三)之数据库管理工具Navicat

    前言 mysql安装完后默认只有命令行工具,所以我们可以下载一些数据库管理工具Navicat Navicat使用 首先建立一个连接选择mysql,填写信息 发现多了一个localhost,双击,打开连 ...

  2. luogu题解 P1099 【树网的核】树的直径变式+数据结构维护

    题目链接: https://www.luogu.org/problemnew/show/P1099 https://www.lydsy.com/JudgeOnline/problem.php?id=1 ...

  3. 链接校验——是否是协议http://或https://开头的

    if(str.substr(0,7)!="http://" && str.substr(0,7)!="https://"){ return 'y ...

  4. 05 Python网络爬虫的数据解析方式

    一.爬虫数据解析的流程 1.指定url 2.基于requests模块发起请求 3.获取响应中的数据 4.数据解析 5.进行持久化存储 二.解析方法 (1)正则解析 (2)bs4解析 (3)xpath解 ...

  5. vue中v-if和v-for优先级

    v-for和v-if不应该一起使用,必要情况下应该替换成computed属性.原因:v-for比v-if优先,如果每一次都需要遍历整个数组,将会影响速度,尤其是当之需要渲染很小一部分的时候.   错误 ...

  6. Hadoop网页监控配置

    接之前的内容http://www.cnblogs.com/jourluohua/p/8734406.html 在之前那的内容中,仅实现了Hadoop的安装和运行,距离实际使用还有很远.现在先完成一个小 ...

  7. mysql统计表中条目个数的方法举例

    说明:以下标红且加大括号的均需要替换为实际待查询的表名或数据库名. [1].统计某张或某几张表的数据量: select count(*) from {TABLE_NAME}; #or select c ...

  8. signal,blinker:信号(看我脸色行事)

    signal 什么是信号(signal)? 信号在linux中被用来进行进程间的通信和异步处理,简单地可以理解会为回调函数,当发送一个信号时,会触发相应的操作.python中的signal模块便是用来 ...

  9. redis如何查看主从状态信息master和salve

    首先你需要连接上redis [root@localhost src]# ./redis-cli -p 6384 --第一步从客户端命令工具连接redis 127.0.0.1:6384> auth ...

  10. Summer training round2 #9(Training28)

    A:签到题 C:模拟搜索题 #include <bits/stdc++.h> #include <cstring> #include <iostream> #inc ...