进程ID

1 进程id是唯一的。(不会有进程id一样的两个进程)

2进程id是可复用的,一个进程销毁后,它的id号可以被新的进程使用。但是Unix采用了延迟复用的算法,也就是进程   销毁后它的id不会立即被使用。

3 进程id为0的是调度进程。这是系统进程,是内核的一部分。

4 进程id为1的是init进程。init进程读取初始化文件/etc/rc*files 或者/etc/inittab,以及在/etc/init.d中的文件,使系统处于      某种状态。 init进程是用户进程,而不是系统进程。

进程id相关函数

  1. #include <unistd.h>
  2. pid_t getpid(void);
  3. Returns: process ID of calling process
  4. pid_t getppid(void);
  5. Returns: parent process ID of calling process
  6. uid_t getuid(void);
  7. Returns: real user ID of calling process
  8. uid_t geteuid(void);
  9. Returns: effective user ID of calling process
  10. gid_t getgid(void);
  11. Returns: real group ID of calling process
  12. gid_t getegid(void);
  13. Returns: effective group ID of calling process

创建新进程

#include <unistd.h>
pid_t fork(void);
Returns: 0 in child, process ID of child in parent,−1 on error
Unix可以使用系统函数fork()创建一个新进程。
    fork()执行一次返回两次。
    返回值:
        0: 
          表示子进程
        子进程id: 表示父进程
     子进程可以通过getppid()来获取父进程id,所以只需要返回0,表示创建成功即可.而对于父进程来说,他无从得知子进程的id,因此在创建的时候就应该吧子进程的Id号返回给他。

    我们知道,每个进程都会涉及到进程控制块、正文段、数据段,三部分内容。
    进程控制块是每个进程独有的,这就不用多说。 
    正文段里面是程序的指令,都是只读的,因此父进程和子进程可以共享这部分内容 。share
    数据段:  子进程会拷贝一份父进程的数据段(数据空间、堆、栈)。注意:这里是copy而不是share

    由于我们知道,一般创建子进程后,进阶着就是使用exec替换子进程为一个新的程序了,这是父进程的数据段内容就没什么用了。因此,现代系统在实现的时候,采用了写时复制copy-on-write(COW)。该方法就是内核将数据段设置为共享share,但它是只读的,当父进程或者子进程下需要对数据进行修改时,就自己copy一个副本。

    Example
#include "apue.h"
#include "myerr.h"
int globvar=6;/*external variable in initialized data */
char buf[] = "a write to stdout\n";
int
main(void)
{
int var; /* automatic variable on the stack */
pid_t pid;
var = 88;
if (write(STDOUT_FILENO, buf, sizeof(buf)-1) != sizeof(buf)-1)
err_sys("write error");
printf("before fork\n"); /* we don’t flush stdout */
if ((pid = fork()) < 0) {
err_sys("fork error");
}else if (pid == 0) { /* child */
globvar++; /* modify variables */
var++;
}else {
sleep(2); /* parent */
}
printf("pid = %ld, glob = %d, var = %d\n", (long)getpid(), globvar, var);
exit(0);
}
执行结果:
windeal@ubuntu:~/Windeal/apue$ ./exe
a write to stdout
before fork
pid = 4523, glob = 7, var = 89
pid = 4522, glob = 6, var = 88
windeal@ubuntu:~/Windeal/apue$

在这个例子中,我们在子进程中对globvar和var都进行自加,然后又在父进程中sleep(2),使得子进程先执行。
最终结果,父进程的数据都没变,子进程globvar和var都变成了新的值。
    从例子中可以看出,正文段是共享的,都使用了printf语句(你要说是copy,我就不跟你辩了。。。)
vfork()
    功能与fork()基本相似。

    不同点:
        vfork保证子进程先执行,也就是子进程执行了exec程序或者exit后才执行fork()。如果子进程中有依赖父进程的下一步动作才能执行的部分,可能会导致死锁。
        vfork创建的子进程会共享父进程的数据段。也就是说它会改变父进程的数据。
#include "apue.h"
#include "myerr.h"
int globvar=6;/*external variable in initialized data */
int
main(void)
{
int var; /* automatic variable on the stack */
pid_t pid;
var = 88;
printf("before vfork\n"); /* we don’t flush stdio */
if ((pid = vfork()) < 0) {
err_sys("vfork error");
}else if (pid == 0) { /* child */
globvar++; /* modify parent’s variables */
var++;
_exit(0); /* child terminates */
}
/* parent continues here */
printf("pid = %ld, glob = %d, var = %d\n", (long)getpid(), globvar, var);
exit(0);
}

执行结果:
windeal@ubuntu:~/Windeal/apue$ ./exe
before vfork
pid = 6298, glob = 7, var = 89
windeal@ubuntu:~/Windeal/apue$

可以看到父进程globvar和var被子进程改变了。

        vfork()被一些版本视为过时的接口,一般不使用。所以不必过多研究,多用fork()来创建新进程即可。


APUE学习笔记——8.1-8.4 进程基础的更多相关文章

  1. apue学习笔记(第七章 进程环境)

    本章将了解进程的环境. main函数 C程序总是从main函数开始执行,main函数的原型是: int main(int argc,char *argv[]); 其中,argc是命令行参数的数目,ar ...

  2. APUE学习笔记——10.9 信号发送函数kill、 raise、alarm、pause

    转载注明出处:Windeal学习笔记 kil和raise kill()用来向进程或进程组发送信号 raise()用来向自身进程发送信号. #include <signal.h> int k ...

  3. APUE学习笔记3_文件IO

    APUE学习笔记3_文件IO Unix中的文件IO函数主要包括以下几个:open().read().write().lseek().close()等.这类I/O函数也被称为不带缓冲的I/O,标准I/O ...

  4. 大数据学习笔记——Java篇之网络编程基础

    Java网络编程学习笔记 1. 网络编程基础知识 1.1 网络分层图 网络分层分为两种模型:OSI模型以及TCP/IP网络模型,前者模型分为7层,是一个理论的,参考的模型:后者为实际应用的模型,具体对 ...

  5. [原创]java WEB学习笔记49:文件上传基础,基于表单的文件上传,使用fileuoload 组件

    本博客为原创:综合 尚硅谷(http://www.atguigu.com)的系统教程(深表感谢)和 网络上的现有资源(博客,文档,图书等),资源的出处我会标明 本博客的目的:①总结自己的学习过程,相当 ...

  6. [学习笔记] 多项式与快速傅里叶变换(FFT)基础

    引入 可能有不少OIer都知道FFT这个神奇的算法, 通过一系列玄学的变化就可以在 $O(nlog(n))$ 的总时间复杂度内计算出两个向量的卷积, 而代码量却非常小. 博主一年半前曾经因COGS的一 ...

  7. C++学习笔记(一):C++基础知识

    一.C++基础知识 新的数据类型 C语言中的数据类型 C++中新的数据类型 思考:新的数据类型有什么好处?请看下面的代码: 可以见得:新的类型使整个程序更加简洁,程序变得易读易懂!这个就是bool类型 ...

  8. 数字图像处理学习笔记之一 DIP绪论与MATLAB基础

    写在前面的话 数字图像处理系列的学习笔记是作者结合上海大学计算机学院<数字图像处理>课程的学习所做的笔记,使用参考书籍为<冈萨雷斯数字图像处理(第二版)(MATLAB版)>,同 ...

  9. java学习笔记(1)java的基础介绍 、JDK下载、配置环境变量、运行java程序

    java工程师是开发软件的 什么是软件呢? 计算机包括两部分: 硬件: 鼠标.键盘.显示器.主机箱内部的cpu.内存条.硬盘等 软件: 软件包括:系统软件和应用软件 系统软件:直接和硬件交互的软件:w ...

随机推荐

  1. [leetcode刷题笔记]Implement Trie (Prefix Tree)

    题目链接 一A,开森- ac代码: class TrieNode { // Initialize your data structure here. char content; boolean isW ...

  2. 前端学习笔记之Z-index详解

    CSS当中的z-index属性看起来足够简单,但是如果你真的想了解它是如何工作的话,在这简单的表面之下,又有许多值得探究的内容. 在这篇教程中,通过探究层叠上下文和一系列实际的例子,我们将会阐明z-i ...

  3. android与linux之间的关系

    篇一(system/core/init/init.c): 对Android感兴趣的朋友都知道,Android系统是建立在Linux内核之上的.那么Linux内核和Android什么关系?Linux内核 ...

  4. java处理json的工具类(list,map和json的之间的转换)

    需要下载第三方的jar :net.sf.json import java.io.BufferedReader; import java.io.InputStream; import java.io.I ...

  5. COJS:1829. [Tyvj 1728]普通平衡树

    ★★★   输入文件:phs.in   输出文件:phs.out   简单对比 时间限制:1 s   内存限制:128 MB [题目描述] 您需要写一种数据结构(可参考题目标题),来维护一些数,其中需 ...

  6. 【Network Architecture】SegNet论文解析(转)

    文章来源: https://blog.csdn.net/fate_fjh/article/details/53467948 Introduction 自己制作国内高速公路label,使用SegNet训 ...

  7. Zookeeper java api

     Zookeeper java api 主要有以下几个: 方法名称 描述 String create(final String path, byte data[], List acl, CreateM ...

  8. JVM与垃圾回收机制(GC)和类的生命周期

    JVM运行时数据区 GC(垃圾回收机制) 什么是垃圾回收机制: 在系统运行过程中,会产生一些无用的对象,这些对象占据着一定的内存,如果不对这些对象清理回收无用的是对象,可能会导致内存的耗尽,所以垃圾回 ...

  9. ng-options 如何实现其中一项option禁选

    <select class="form-control" ng-model="functionPaymentMethod" ng-options=&quo ...

  10. React 16.3.0 发布,构建用户界面的 JavaScript 库

    React 16.3.0 已发布,React 是 Facebook 推出的一个为数据提供渲染为 HTML 视图,用来构建用户界面的开源 JavaScript 库. React 视图通常采用包含以自定义 ...