日期:2019/3/23

内容:Linux下与多进程相关的函数。

 

 

进程基本知识

  • 定义

应用程序关于某数据集合上的一次运行活动。

  • 特点

·操作系统进行资源分配和调度的基本单位

·进程是程序的一次执行过程。进程是动态的,程序是静态的。

·同一程序同时运行于若干个数据集合上,该程序将对应与若干个不同的进程。

·每个进程拥有独立的地址空间。地址空间包括代码段、数据段和堆栈段。

·进程之间的地址空间是隔离的。一个进程崩溃不会影响另一个进程,一个进程崩溃不会影响到操作系统。(一个程序开了多个进程,全局变量也不会共享)

fork函数

  • 作用:创建一个子进程
  • 返回值:

在父进程中,fork返回新创建子进程的进程PID;

在子进程中,fork返回0;

如果出现错误,fork返回一个负值;

  • 实现细节

·OS为子进程创建一个PCB(Process Control Block, 进程控制块,其实质是一个结构体)

·复制代码和数据到子进程的地址空间(PID不复制)

  • 获取PID

当前进程

获取子进程PID

获取父进程PID

子进程

getpid()

getppid()

父进程

pid=fork()

getpid()

 

获取PID代码样例

/*************************************************************************

    > File Name: testfork.c

    > Author: sinkinben

    > E-mail: sinkinben@qq.com

    > Created Time: Sat 23 Mar 2019 08:13:00 AM CST

************************************************************************/

 

#include <stdio.h>

#include <unistd.h>

#include <sys/types.h>

#include <sys/wait.h>

int main()

{

    //pid_t pid = fork();

    pid_t pid;

    pid = fork();

    //sleep(3); //3sec

    if (pid == 0)

        printf("In child process: child pid = %d, parent pid = %d\n", getpid(), getppid());

    else

        printf("In parent process: parent pid = %d, child pid = %d\n", getpid(), pid);

    wait(NULL);

    return
0;

}

 

/*

* 父进程先于子进程退出

* init是1号进程,接管子进程

* 所以in child process, getppid()总是返回1

* 解决办法:父进程调用sleep

* 正解:调用wait,让父进程等待子进程结束

*/

 

 

  • 并发特性与隔离特性

并发

·二者并发运行,输出交织。

·代码段相同:父进程从fork返回处执行(返回值为子进程PID);子进程从fork返回处执行(返回值0)

隔离

·地址空间隔离,仅能访问自己的地址空间

·出现非法访存,只影响当前进程

·全局变量也不共享

 

并发和隔离样例代码

/*************************************************************************

    > File Name: concurrency.c

    > Author: sinkinben

    > E-mail: sinkinben@qq.com

    > Created Time: Sat 23 Mar 2019 08:38:19 AM CST

************************************************************************/

 

#include <stdio.h>

#include <unistd.h>

#include <stdlib.h>

static
int global = 0;

void child()

{

    int i = 0;

    for (i = 0; i < 5; i++)

    {

        puts("child");

        printf("global = %d\n", global++);

        sleep(1);

    }

}

void parent()

{

    int i = 0;

    for (i = 0; i < 5; i++)

    {

        puts("parent");

        printf("global = %d\n", global++);

        sleep(1);

    }

}

 

int main()

{

    pid_t pid = fork();

    if (pid)

        parent();

    else

        child();

    return
0;

}

 

运行结果

exec系列

名词解析:

exec:execute

l:list,表示参数是列表形式

v:vector,表示参数是数组形式

p:path,允许exec系列函数使用系统环境变量PATH下的路径

全家桶如下。

头文件:unistd.h

返回值:成功无返回值,失败-1.

函数

原型

描述

execl

int execl(const char *path, const char *arg, ...

·当前进程地址空间清空

·将path指定的可执行程序的代码和数据装入当前地址空间

·参数可变,最后一个必须NULL

·可以是相对/绝对路径

·失败原因存于errno(一个Linux全局变量)中,可通过perror()打印。

·execl成功的话,会执行另外的程序,因此成功无返回值。

·参数格式:路径+程序名+参数1,2,3...,NULL

execv

int execv(const char *path, char *const argv[]);

·argv数组最后一项必须为NULL

·argv[]={程序名,参数1,2,3...,NULL}

·参数格式:路径+argv

execlp

int execlp(const char *file, const char *arg, ...

·允许使用PATH环境变量作为参数file

execvp

int execvp(const char *file, char *const argv[]);

 

execl样例代码

/*************************************************************************

    > File Name: testexecl.c

    > Author: sinkinben

    > E-mail: sinkinben@qq.com

    > Created Time: Sat 23 Mar 2019 08:52:03 AM CST

************************************************************************/

 

#include <stdio.h>

#include <unistd.h>

int main()

{

    puts("before execl");

    int error_code = execl("/bin/echo", "echo", "sin", "cos", NULL);

    if (error_code < 0)

        perror("error execl");

    puts("after execl");

    return
0;

}

 

 

execv样例代码

/*************************************************************************

    > File Name: testexecv.c

    > Author: sinkinben

    > E-mail: sinkinben@qq.com

    > Created Time: Sat 23 Mar 2019 08:59:16 AM CST

************************************************************************/

 

#include <stdio.h>

#include <unistd.h>

int main()

{

    puts("before execv(p)");

    char *argv[] = { "ls", "-a", NULL};

    //int error = execv("/bin/ls",argv);

    int error = execvp("ls", argv);

    if(error == -1)

        perror("error");

    puts("after execv(p)");

    return
0;

 

}

 

 

exit

·头文件:stdlib.h

·原型:void exit(int status);

·功能

>>正常退出当前进程

>>将status & 0XFF作为退出码返回给父进程

·预定义常量

>>EXIT_SUCCESS, 为0,表示正常退出

>>EXIT_FAILURE,为非0,表示异常退出

>>在Linux shell中,$?可以获取程序的退出码

·main与exit

>>return 0 相当于exit(SUCCESS)

>>return !0 相当于exit(FAILURE)

>>start.asm(计算机组成原理知识:main返回的上一层是start.asm)

global _start

extern main

extern exit

_start:

call main

add esp,

push eax //作为参数eax->[ebp+8]传给exit

call exit

add esp, 4

hlt

 

exit与$?代码实例

#include <stdio.h>

#include <stdlib.h>

int main()

{

    exit(233);

}

运行结果

atexit

·头文件:stdlib.h

·原型:int atexit(void (*function)(void)); (参数是函数指针)

·功能

>>注册回调函数,进程正常结束时,function被调用

>>如果注册多个,以与注册相反的顺序调用

 

wait

·头文件:sys/types.h, sys/wait.h

·原型:pid_t wait(int *status);

·功能

>>等待子进程结束

>>如果status非空,子进程退出码保存在status

·退出码

进程可能由于不同原因退出。主动调用exit退出,或接收信号退出。

查询退出原因的宏

WIFEXITED(status)

当子进程exit(0)时,为真。

WEXITSTATUS(status)

当子进程exit(!0)时,返回退出码

WIFSIGNALED(status)

当子进程接收信号后退出,为真

WTERMSIG(status)

当子进程接收信号后退出,返回导致退出的信号码

 

OSLab多进程的更多相关文章

  1. Python中的多进程与多线程(一)

    一.背景 最近在Azkaban的测试工作中,需要在测试环境下模拟线上的调度场景进行稳定性测试.故而重操python旧业,通过python编写脚本来构造类似线上的调度场景.在脚本编写过程中,碰到这样一个 ...

  2. 取代SharedPreferences的多进程解决方案

    Android的SharedPreferences用来存储一些键值对, 但是却不支持跨进程使用. 跨进程来用的话, 当然是放在数据库更可靠啦, 本文主要是给作者的新库PreferencesProvid ...

  3. python 多进程使用总结

    python中的多进程主要使用到 multiprocessing 这个库.这个库在使用 multiprocessing.Manager().Queue时会出问题,建议大家升级到高版本python,如2 ...

  4. Nginx深入详解之多进程网络模型

    一.进程模型        Nginx之所以为广大码农喜爱,除了其高性能外,还有其优雅的系统架构.与Memcached的经典多线程模型相比,Nginx是经典的多进程模型.Nginx启动后以daemon ...

  5. Python的多线程(threading)与多进程(multiprocessing )

    进程:程序的一次执行(程序载入内存,系统分配资源运行).每个进程有自己的内存空间,数据栈等,进程之间可以进行通讯,但是不能共享信息. 线程:所有的线程运行在同一个进程中,共享相同的运行环境.每个独立的 ...

  6. 进击的Python【第十章】:Python的socket高级应用(多进程,协程与异步)

    Python的socket高级应用(多进程,协程与异步)

  7. PHP的pcntl多进程

    PHP使用PCNTL系列的函数也能做到多进程处理一个事务.比如我需要从数据库中获取80w条的数据,再做一系列后续的处理,这个时候,用单进程?你可以等到明年今天了...所以应该使用pcntl函数了. 假 ...

  8. 初探PHP多进程

    h2:first-child, body>h1:first-child, body>h1:first-child+h2, body>h3:first-child, body>h ...

  9. gdb进程调试,多进程调试

    1.单进程的调试 常规的通过gdb cmd这种方式开启调试,特别说明的是通过attach的方法附加到一个指定的进程上去进行调试,这种方法适合于调试一个已经运行的进程,具体用法:  gdb -p [pi ...

随机推荐

  1. Activiti任务认领

    Activiti任务认领 TaskService taskService; taskService.setAssignee(String taskId, String userId);taskServ ...

  2. 【Apache】Apache服务的基本概念(二)

    Apache服务的基本概念 Apache安装请参照:[Apache]Apache服务的安装(一) 1.端口 apache默认监听TCP协议端口80端口 2.apache服务 apache服务默认会启动 ...

  3. [SQL]查询最新的数据

    在设计数据库的时候,把数据的跟新,删除都是软操作,就是都是变成了增加,也是会需要读取最新的那条数据 ' 获取最新时间的数据 Select a.* FROM SortInfo a,(SELECT SnS ...

  4. 强连通缩点— HDU1827

    强连通缩点以后最终形成的是一棵树 我们可以根据树的性质来看缩点以后的强连通分量图,就很好理解了 /* gyt Live up to every day */ #include<cstdio> ...

  5. Django框架之验证码生成示例

    一.生成随机颜色的图片 1)前端代码展示 <!DOCTYPE html> <html lang="en"> <head> <meta ch ...

  6. mybatis 中文做参数报错

    一个简单的查询,如果参数中有中文.如下: <select id="xxxx" resultType="hashmap"> select * from ...

  7. Softmax && Cross-entropy Error

    softmax 函数,被称为 归一化指数函数,是sigmoid函数的推广. 它将向量等比压缩到[0, 1]之间,所有元素和为1. 图解: Example: softmax([1, 2, 3, 4, 1 ...

  8. 219.01.19 bzoj3252: 攻略(长链剖分+贪心)

    传送门 长链剖分好题. 题意:给一棵带点权的树,可以从根节点到任一叶节点走kkk次,走过的点只能计算一次,问kkk次走过的点点权值和最大值. 思路: 考虑将整棵树带权长链剖分,这样链与链之间是不会重复 ...

  9. 2018.11.30 spoj220 Relevant Phrases of Annihilation(后缀数组+二分答案)

    传送门 代码: 先用特殊字符把所有字符串连接在一起. 然后二分答案将sasasa数组分组. 讨论是否存在一个组满足组内对于每一个字符串都存在两段不相交字串满足条件. #include<bits/ ...

  10. 第01章:MongoDB简介

    ①MongoDB是什么 MongoDB是一个使用C++编写的.开源的.面向文档的NoSQL(Not Only SQL)数据库,也是当前最热门的NoSql数据库之一. ②MongoDB特点 1.高性能. ...