Linux多进程

来源:互联网 发布:网络信息推广的文字 编辑:程序博客网 时间:2024/06/02 04:26

Linux进程状态:


R (TASK_RUNNING),可执行状态。

S (TASK_INTERRUPTIBLE),可中断的睡眠状态。

D (TASK_UNINTERRUPTIBLE),不可中断的睡眠状态。

T (TASK_STOPPED or TASK_TRACED),暂停状态或跟踪状态。
Z (TASK_DEAD – EXIT_ZOMBIE),退出状态,进程成为僵尸进程。

X (TASK_DEAD – EXIT_DEAD),退出状态,进程即将被销毁。


链接:http://blog.csdn.net/huzia/article/details/18946491


进程标识


获取进程标志号(pid)的API,主要有两个函数:getpid和getppid


需要包含的头文件:<sys/types.h>, <unistd.h> 

函数原型:pid_t getpid(void) 

功能:获取当前进程ID 

返回值:调用进程的进程ID


函数原型:pid_t getppid(void) 

功能:获取父进程ID 

返回值:调用进程的父进程ID


C 进程内存布局说明


text:代码段。存放的是程序的全部代码(指令),来源于二进制可执行文件中的 代码 部分
initialized data(简称data段)和uninitialized data(简称bss段)组成了数据段。
malloc是从heap(堆)中分配空间的
stack(栈)存放的是动态局部变量。


环境变量的获取与设置


需要包含的头文件:<stdlib.h>

函数原型: 

char * getenc(const char * name) 

返回字符指针,该指针指向变量名为name的环境变量的值字符串。


int putenv(const char * str) 

将“环境变量=环境变量值”形式的字符创增加到环境变量列表中;如果该环境变量已存在,则更新已有的值。


int setenv(const char * name, const char * value, int rewrite) 

设置名字为name的环境变量的值为value;如果该环境变量已存在,

且rewrite不为0,用新值替换旧值;rewrite为0,就不做任何事。


fork

函数原型:pid_t fork (void)


函数原型:pid_t vfork (void)

与fork区别:

1.fork数据段拷贝。vfork数据段共享

2.fork执行次序不定,vfork子进程先运行


头文件:#include<stdlib.h>

函数原型:int system(const char *string)

功能:调用fork产生子进程,由子进程来调用 /bin/sh -c string来执行参数string所代表的命令

例:system("ls -al /etc/passwd");


fork函数被调用1次(在父进程中被调用),

但返回2次(父、子进程中各返回一次)。

两次返回的区别是子进程的返回值是0,

而父进程的返回值则是子进程的进程ID。

(出错返回负数)


父、子进程完全一样(代码共享、数据拷贝),

子进程从fork内部开始执行;父、子进程从fork返

回后,接着执行下一条语句。


一般来说,在fork之后是父进程先执行还是子进程先执行是不确定的,

应用程序员无法控制。


fork会导致子进程继承父进程打开的文件描述符,

其本质是将父进程的整个文件描述符表复制一份,

放到子进程的PCB中。因此父、子进程中相同文件

描述符(文件描述符为整数)指向的是同一个文件

表元素,这将导致父(子)进程读取文件后,

子(父)进程将读取同一文件的后续内容。


wait

需要包含的头文件: <sys/types.h>、<sys/wait.h> 

函数原型:pid_t wait(int * status) 

功能:等待进程结束。 

返回值:若成功则为子进程ID号,若出错则为-1. 

参数说明: status:用于存放进程结束状态。

wait函数用于使父进程阻塞,直到一个子进程结束。父进程调用wait,该父进程可能会:
阻塞(如果其所有子进程都还在运行)。
带子进程的终止状态立即返回(如果一个子进程已终止,正等待父进程存取其终止状态)。
出错立即返回(如果它没有任何子进程)。


WIFEXITED: 这个宏是用来判断子进程的返回状态是不是为正常,如果是正常退出,这个宏返回真。 WEXITSTATUS: 用来返回子进程正常退出的状态值。 

WIFSIGNALED: 用来判断子进程的退出状态是否是非正常退出,若非正常退出时发送信号,则该宏返回真。 WTERMSIG: 用来返回非正常退出状态的信号number。 


exec 的机制:


exec启动一个新程序,替换原有的进程,PID不会变。


exec 的用法:



头文件:#include <unistd.h>

函数原型:int execl (const char *path, const char *arg1, ...)

参数:path:被执行的程序名(含完整路径)。

  arg1-argn:被执行程序所需的命令行参数,含程序名,以空指针结束。

例:execl("/bin/ls","ls","-al","/etc/passwd",(char *)0);


头文件:#include <unistd.h>

函数原型:int execlp (const char *path, const char *arg1, ...)

参数:path:被执行的程序名(不含路径,从path中查找该程序)。

  arg1-argn:被执行程序所需的命令行参数,含程序名,以空指针结束。


头文件:#include <unistd.h>

函数原型:int execlv (const char *path, char * const argv[])

参数:path:被执行的程序名(含完整路径)。

  argv[]:被执行程序所需的命令行参数数组。

例:char *argv[]={"ls","-al","/etc/passwd",(char*)0};

execv("/bin/ls",argv);



函数原型: int execle(const char * pathname,const char * arg0, ... (char *)0, char * const envp [] )

返回值: exec执行失败返回-1,成功将永不返回(想想为什么?)。

参数:

pathname:新程序的二进制文件的全路径名 

arg0:新程序的第1个命令行参数

argv[0],之后是新程序的第2、3、4…个命令行参数,以(char*)0表示命令行参数的结束 

envp:新程序的环境变量


gdb 调试多进程程序的技巧


对多进程程序进行调试,存在一个较大的难题,那就是当程序调用fork产生子进程后,gdb跟踪的是父进程,无法进入到子进程里去单步调试子进程。这样一来,如果子进程中的代码运行出错的话,将无法进行调试。因此想调试子进程的话,需要一点技巧:


在子进程的入口处加入sleep(20)函数,以使子进程在被创建后能暂时停止。
用ps查看子进程的pid,假定pid为222,则输入命令:gdb程序名称222。从而再运行一个调试程序,使得gdb attach到子进程。
用gdb的break命令在子进程中设定断点。
用gdb的continue,恢复子进程的运行。
等待sleep的睡眠时间到达,从而子进程将在断点处停下来。


有5冲方式结束进程: 

正常结束: 

1.从main函数返回 

2.调用exit 

3.调用_exit
非正常结束:

 4.调用abort 

 5.被信号中止


exit 函数与 _exit 函数


需要包含的头文件:<stdlib.h>、<unistd.h> 

函数原型: void exit(int status)、 void _exit(int status)


这两个函数的功能都是使进程正常结束。 

_exit:立即返回内核,它是一个系统调用 

exit:在返回内核钱会执行一些清理操作,这些清理操作包括调用exit handler,以及彻底关闭标准I/O流(这回使得I/O流的buffer中的数据被刷新,即被提交给内核),它是标准C库中的一个函数。



Exit handler


Exit handler 是程序员编写的函数,进程正常结束时,它们会被系统调回。这使程序员具备了在进程正常结束时,控制进程执行某些善后操作的能力。 使用Exit handler,需要程序员完成两件事情:编写Exit handler函数;调用atexit或on_exit向系统注册Exit handler(即告知系统需要回调的Exit handler函数是谁)


需要包含头的文件:<stdlib.h> 

函数原型:


int atexit(void (* func)(void))

int on_exit(void (* func)(int, void *),)


功能: atexit注册的函数func没有参数;

   on_exit注册的函数func有一个int型参数,系统调用回调func时将向该参数传入进程的退出值,func的另一个void *类型参数将会是arg。


(ANSI C中,进程最多可以注册32个Exit handler函数,这些函数按照注册时的顺序被逆序调用。)


转载自实验楼:www.shiyanlou.com

0 0
原创粉丝点击