- 浏览: 724629 次
- 性别:
- 来自: 北京
最新评论
-
wxweven:
Surmounting 写道既然 Java 的跳表那么少,我决 ...
SkipList 跳表 -
暮雪云然:
写的不错,很透彻
Java静态内部类 -
bzhao:
好,赞扬!
Linux信号详解 -
jacktao219:
赞一个~! ,现在正在看redis 所以接触到跳表
SkipList 跳表 -
is_leon:
vote--后还要判断是否为0吧,如果为0则废掉重新置位can ...
现在有一个整数数组,已知一个数出现的次数超过了一半,请用O(n)的复杂度的算法找出这个数
讲到fork, 一个经典的例子如下:
if ((pid = fork()) == 0) {
printf("in child %d\n", getpid());
} else if (pid > 0) {
printf("in parent\n");
} else {
perror("fork");
exit(0);
}
现在, 我要创建5个进程, 每个进程都打印出自己的pid, 写下如下代码:
#include <stdio.h> #include <stdlib.h> #define N_PROCESS 5 int main() { pid_t pid[N_PROCESS]; int i; /* create child process */ for (i = 0; i < N_PROCESS; i++) { if ((pid[i] = fork()) == 0) { printf("in child %d\n", getpid()); } else if (pid[i] > 0) { printf("in parent\n"); } } return 0; }
看似没有问题, 编译运行, 结果令人惊讶:
in parent in parent in parent in parent in parent in child 11799 in parent in parent in parent in parent in child 11799 in parent in parent in parent in child 11807 in parent in parent in parent in child 11803 in parent in parent in parent in parent in parent in child 11805 in child 11799 in parent in child 11804 in parent in parent in child 11799 in parent in parent in child 11806 in child 11808 in parent in parent in parent in child 11803 in child 11809 in parent in parent in child 11802 in parent in parent in child 11799 in child 11801 in parent in parent in parent in child 11799 in parent in child 11804 in parent in child 11811 in child 11799 in child 11801 in parent in child 11815 in parent in parent in parent in child 11802 in child 11812 in parent in child 11799 in child 11801 in child 11813 in parent in parent in parent in child 11800 in parent in parent in parent in child 11799 in parent in child 11804 in child 11810 in child 11817 in parent in parent in child 11802 in child 11812 in child 11819 in child 11799 in child 11801 in parent in parent in child 11816 in parent in parent in child 11802 in parent in child 11814 in child 11799 in child 11801 in parent in child 11815 in child 11818 in parent in child 11800 in parent in child 11822 in parent in parent in child 11800 in parent in parent in child 11824 in child 11799 in child 11801 in child 11813 in parent in child 11823 in parent in child 11800 in child 11820 in parent in parent in parent in child 11800 in parent in child 11822 in child 11825 in child 11799 in child 11801 in child 11813 in child 11821 in parent in parent in child 11800 in child 11820 in parent in child 11828 in child 11799 in child 11801 in child 11813 in child 11821 in child 11826 in parent in child 11800 in child 11820 in child 11827 in child 11829
数一数, 程序创建了31个子进程! 怪哉, 哪里出问题了呢?
仔细分析一下, 第一次fork调用时, i = 0, fork完成后, 子进程和父进程拥有相同的存储,
即两者的 i = 0,然后父进程执行parent代码段, 打印 "in parent", 子进程执行child代码
段, 打印自己的pid. 关键是, 到了这里, 子进程没有退出, 处于for循环中, 于是子进程接着
执行 i = 1 时的for循环, 子进程执行fork, 又创建子进程, 这样就产生孙子进程. 按照这种
步骤, 孙子进程又会创建子进程....稍微分析一下, 可以得到递推公式,如果想创建n个子进程,
将执行 2^n - 1次fork调用并产生2^n-1个子进程, 真是子子孙孙无穷尽也...
可见, 问题的关键是, 终止子进程继续执行for循环, 修改代码:
#include <stdio.h> #include <stdlib.h> #define N_PROCESS 5 int main() { pid_t pid[N_PROCESS]; int i; /* create child process */ for (i = 0; i < N_PROCESS; i++) { if ((pid[i] = fork()) == 0) { printf("in child %d\n", getpid()); exit(0); /* 让子进程退出 */ } else if (pid[i] > 0) { printf("in parent\n"); } } return 0; }
运行结果如下:
in parent in child 12037 in parent in parent in child 12039 in child 12038 in parent in child 12040 in parent in child 12041
这次只创建了5个进程, 但parent代码段执行了5次, 不符合我们的要求, 再改:
#include <stdio.h> #include <stdlib.h> #define N_PROCESS 5 int main() { pid_t pid[N_PROCESS]; int i; /* create child process */ for (i = 0; i < N_PROCESS; i++) { if ((pid[i] = fork()) == 0) { printf("in child %d\n", getpid()); exit(0); /* 让子进程退出 */ } } printf("in parent\n"); return 0; }
运行结果如下:
in child 12072 in parent in child 12074 in child 12075 in child 12073 in child 12076
嘎嘎, 这是我们期望的结果.
发表评论
-
Virtualbox下Windows和Linux实现文件互传
2012-07-17 21:05 33841 Windows安装好Linux虚拟机 2 在Lin ... -
Memcached源码分析之网络模型篇
2012-03-02 01:46 4142memcached 采用多线程的工作方式, 主线程接收连接, ... -
Memcached源码分析之内存管理篇
2012-02-26 15:04 12076使用命令 set(key, value) ... -
多线程与volatile变量
2012-02-25 17:07 5427volatile 修饰的变量表示改变量的值是易变的,编译 ... -
items
2011-11-12 19:30 71 上肢长 2 上臂长 ... -
fds
2011-11-12 19:23 10身高(静态) 眼高 ... -
xml
2011-11-12 18:58 7<item idx = "1" ... -
fff
2011-11-12 18:30 8上肢长 上臂长 两下颌角宽 两眼内宽 两耳屏点间 ... -
(转) memcached采用的网络模型
2011-10-12 01:58 12memcached采用的网络模型 ... -
Nginx 内存池
2011-10-12 01:46 7nginx的内存管理,主要是用来实现防止内存泄露,和内存碎片, ... -
Nginx负载均衡
2011-10-12 01:40 10nginx的upstream目前支持5种方式的分配 ... -
守护进程的实现
2011-09-30 01:43 18486个步骤 步骤1:创建子进程,杀死父进程,目的是为了步 ... -
非阻塞connect的实现
2011-09-30 01:12 14790步骤1: 设置非阻塞,启动连接 实现非阻塞 connect ... -
Memcached内存管理机制
2011-09-29 20:57 2358Slab 分配机制 Memcache ... -
关于大端法和小端法
2011-09-28 23:15 2354typedef union { int n; ... -
vim配置文件精简版
2011-09-19 09:37 1950"Get out of VI's compatibl ... -
(转) Linux 的僵尸(zombie)进程
2011-09-17 20:29 3191原文地址: http://cool ... -
Linux信号详解
2011-09-17 01:02 36355一 信号的种类 可靠信号与不可靠信号, 实时信号与非实时信号 ... -
消息队列
2011-09-15 22:16 12241一 应用场景 有很多业务, 客户端和内网都要进行数据传 ... -
vim + taglist + ctags + cscope 简单使用
2011-09-08 21:58 3560ctags用来跳转, taglist用来列出当前文件的变量, ...
相关推荐
fork 创建多个子进程是指通过 fork 系统调用创建多个子进程,每个子进程可以执行不同的任务。下面我们将讨论三种常见的 fork 创建多个子进程的方法。 第一种方法:同时创建多个子进程 该方法通过在主进程中使用 ...
`fork()` 是 Linux 和其他类 Unix 操作系统中的一个重要系统调用,用于创建一个与当前进程几乎完全一样的新进程,即子进程。子进程继承了父进程的大部分属性,如打开的文件描述符、环境变量等,但它是一个独立的进程...
它创建了一个完全相同的子进程副本,并返回一个进程标识符(PID)。fork 函数的返回值在父进程和子进程中不同:在父进程中,返回子进程的 PID;在子进程中,返回 0。 fork 函数的基本功能可以通过以下示例程序来...
2. 如果其中一个进程的输出结果是 “pid1:1001,pid2:1002”,请写出其他进程的输出结果(不考虑进程执行顺序)。 #### 解析 **预备知识** 为了更好地理解此题,首先需要了解一些关于 Linux 进程的基础知识: 1. ...
2. **父子进程交互**:每个子进程都有机会成为下一个`fork()`函数的调用者,从而创建更多的子进程。这种递归创建方式使得程序输出结果更加复杂。 3. **程序结束**:所有子进程创建完成后,主进程和其他子进程都将...
\n")`,`stdout`的缓冲区会在遇到`\n`时被刷新,所以子进程不会继承这个已刷新的缓冲,从而只会在屏幕上看到一次"fork!"。 此外,当我们把程序的输出重定向到文件时,行为可能会有所不同。因为重定向通常会导致标准...
2. **返回值**:`fork()`调用后,执行流被分成两个分支,一个是父进程,另一个是子进程。两者都会继续执行`fork()`之后的语句,但各自的执行上下文不同。 三、父子进程通信 由于`fork()`后的两个进程共享某些资源...
当一个进程调用`fork()`函数时,系统会为新进程分配所需的资源,并将父进程的状态复制给子进程。这意味着除了少数几个特定值外,子进程与父进程具有相同的内存空间、环境变量和其他属性。这样的设计使得子进程可以...
2. **守护进程**:通过`fork()`和`exec()`组合,父进程可以创建一个脱离控制终端的后台服务进程(守护进程)。 3. **进程通信**:多个进程之间可以通过管道、套接字或共享内存进行通信。 总结,虽然"fork3()"不是...
在Linux操作系统中,进程是程序执行的一个实例,而`fork()`函数是用于创建新进程的关键系统调用。本文将深入探讨`fork()`函数的工作原理、使用方法及其在Linux进程控制编程中的重要性。 `fork()`函数是C语言标准库...
在解释这个问题之前,我们需要了解一个概念:在语句pid=fork()之前,只有一个进程在执行这段代码,但在这条语句之后,就变成两个进程在执行了,这两个进程的代码部分完全相同,将要执行的下一条语句都是if (pid>0)...
2. **返回值判断**:`fork()` 在父进程和子进程中都会返回一个值,但在父进程中返回的是子进程的进程标识符(PID),而在子进程中返回的是 0。通过这种方式,程序可以根据返回值的不同来区分父进程和子进程。 #### ...
在Linux操作系统中,`fork()`函数是创建新进程的关键接口,它是C标准库中的一个系统调用。这个函数允许一个正在运行的进程(父进程)创建一个与它几乎完全相同的副本,即子进程。理解并熟练使用`fork()`是进行进程...
2. **返回值的区别**:`fork()`函数的返回值用于区分父进程和子进程: - 如果`fork()`返回值小于0,表明子进程创建失败。 - 如果`fork()`返回值等于0,表明这是子进程。 - 如果`fork()`返回值大于0,这个进程ID是...
- 第二个`fork()`再次调用会产生另一个子进程`P2`,`P0`中的`fork()`返回`P2`的PID(例如1002)给`pid2`,之后`P0`完成执行并打印“pid1:1001, pid2:1002”。 - 对于`P2`而言,由于它是`P0`的子进程,因此`pid1`的...
本篇文章将深入探讨如何用Python编写一个守护进程,以及在进程被杀后自动重启的实现方法。 首先,让我们了解守护进程的基本概念。在Unix-like操作系统中,守护进程通常在用户登录会话之外运行,避免受到用户退出或...
2. 运行下面的程序,分析“printf(”fork 1,PID=%d\n“,getpid()); ”为什么会被执行两次。 3. 编译下面的程序 ftree.c,让可执行程序后台运行,用“pstree 进程 ID 号”查看进程树,用“ps”查看进程 ID 号,绘制...
本资源为我的博客《实验3正篇——用户进程》的附件,其中主要包含了实验3的代码实现,注意该代码可能有部分bug,但是在之后的实验中修复了,还包含了许多流程图或者逻辑图,与前篇的部分文件。希望能对感兴趣的人员...