首页 > 系统服务 > 详细

OSLab多进程

时间:2019-03-23 17:41:04      阅读:164      评论:0      收藏:0      [点我收藏+]

日期: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

OSLab多进程

原文:https://www.cnblogs.com/sinkinben/p/10584478.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!