日期:2019/3/23
内容:Linux下与多进程相关的函数。
?
?
应用程序关于某数据集合上的一次运行活动。
·操作系统进行资源分配和调度的基本单位
·进程是程序的一次执行过程。进程是动态的,程序是静态的。
·同一程序同时运行于若干个数据集合上,该程序将对应与若干个不同的进程。
·每个进程拥有独立的地址空间。地址空间包括代码段、数据段和堆栈段。
·进程之间的地址空间是隔离的。一个进程崩溃不会影响另一个进程,一个进程崩溃不会影响到操作系统。(一个程序开了多个进程,全局变量也不会共享)
在父进程中,fork返回新创建子进程的进程PID;
在子进程中,fork返回0;
如果出现错误,fork返回一个负值;
·OS为子进程创建一个PCB(Process Control Block, 进程控制块,其实质是一个结构体)
·复制代码和数据到子进程的地址空间(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: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; ? } ? |
?
·头文件: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); } |
运行结果
原文:https://www.cnblogs.com/sinkinben/p/10584478.html