当前位置:首页 > 开发 > 编程语言 > 编程 > 正文

Linux 进程函数入门

发表于: 2011-09-17   作者:bestchenwu   来源:转载   浏览次数:
摘要:          这里进程的概念就不介绍了。首先介绍fork函数的用法.        fork函数位于unistd.h,Linux对应的进程库位于/sys/types.h中,他提供了pid_t这样的结构体。fork函数被调用到的时 候,被创建的子进程会得到与父进程

 

       这里进程的概念就不介绍了。首先介绍fork函数的用法.

       fork函数位于unistd.h,Linux对应的进程库位于/sys/types.h中,他提供了pid_t这样的结构体。fork函数被调用到的时 候,被创建的子进程会得到与父进程虚拟地址空间相同但是独立的一份拷贝,包括数据、文本等等,甚至会获得与父进程任何打开文件描述符相同的拷贝。fork 函数调用一次,但返回两次。第一次返回给父进程,返回的值是子进程的pid;第二次在子进程中,返回0。以下的代码清楚的说明了上述情况:

       第一个公用文件:csapp.h

 

#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
pid_t Fork(void){
   pid_t pid;
   if((pid=fork())<0){
	   printf("Fork error");
   }
   return pid;
}

 

    第二个是示范程序test.c:

 

#include "csapp.h"
int main(){
    int x=1;
    pid_t pid = Fork();
    if(pid==0){
        printf("printf1 x=%d\n",++x);
    }
    printf("printf2 x=%d\n",--x);
    exit(0);
}

 

  这个程序在运行的时候会按照fork函数的调用方式返回:

 

printf2 x=0   //父进程的输出
printf1 x=2  //子进程的输出
printf2 x=1   //子进程的输出

 

   至于这里为什么父进程优先执行完毕,完全取决于对应的Linux系统的进程调度的实现方式。

 

    其次是waitpid()函数,它的函数声明如下所示:

 

pid_t waitpid(pid_t pid,int *status,int options)

    这个函数有三个参数,第一个参数为等待集合的成员,如果pid>0,则为等待的某一个单独进程,它的进程ID等于pid,如果pid=-1,则表明要等待所有在该进程上创建的子进程。

   第二个参数是waitpid函数会用来存放关于进程存放的状态信息。

   第三个参数是用来规范waitpid函数的行为,默认为WHOHANG(0),表示如果等待集合中的任何子进程都还没有终止,那么就立即返回。

   这个函数返回导致该函数返回的已终止的子进程的PID。

 

 

#include "../process/csapp.h"
#define N 2
int main(){
    pid_t pid[N];
    pid_t reapid;
    int status,i;
    int index=0;
    for(i=0;i<N;i++){
        if((pid[index++]=Fork())==0){
        	exit(100+i);//子进程一创建,就立即退出了
        }
    }
    int j;
    //由于这段代码只会由父进程调用到
    //所以这个pid数组存放的是子进程的PID信息
    for(j=0;j<index;j++){
    	printf("pid[%d]=%d\n",j,pid[j]);
    }
    i=0;
    //waitpid返回导致wait函数退出的pid进程号
    while((reapid=waitpid(pid[i++],&status,0))>0){
         if(WIFEXITED(status)){
        	 printf("child %d normally exit with %d\n",reapid,WEXITSTATUS(status));
         }else{
        	 printf("child %d exit abnormal\n",reapid);
         }
    }
    if(errno!=ECHILD){
    	printf("waitpid error");
    }
    exit(0);
}

 

   这里用到了一点小技巧,在父进程里保存了所有创建的子进程的信息,并有序的终止子进程。程序的输出是:

 

pid[0]=2525
pid[1]=2526
child 2525 normally exit with 100
child 2526 normally exit with 101

 

  最后介绍下linux里关于进程非本地跳转的入门知识

  非本地跳转指的是将控制从一个函数转移到一个当前正在执行的函数,而不需要进行正常的函数调用-返回序列.这样就涉及到两个函数:

 

#include <setjmp.h>
//在env缓冲区中保存当前调用环境,以供后面longjmp调用
//调用环境包括程序计数器、栈指针、通用目的寄存器
int setjmp(jmp_buf env)      //可以看成是catch语句块
//从env缓冲区恢复调用环境,然后触发一个从最近一次初始env的setjmp调用的返回,
//然后setjmp返回,返回值是retval
void longjmp(jmp_buf env,int retval)  //可以看成是throw语句块
 
//她们的扩展版本是sigsetjmp和longjmp 这是可以被信号处理的版本

 

  例子程序如下:

 

#include "../process/csapp.h"
#define N 2
sigjmp_buf buf;
void handler(int sig){
	//longjmp看成是throw语句块
	siglongjmp(buf,2);
}
int main(){
	signal(SIGINT,handler);
	//这里可以把setjmp看成是try...catch里的catch语句块
	if(!sigsetjmp(buf,1)){
		printf("starting\n");
	}else{
		printf("restarting");
	}
	while(1){
		sleep(1);
		printf("processing\n");
	}
	exit(0);
}

 

这个函数运行的输出结果是:

starting
processing
processing
processing
processing
restarting
....
 

Linux 进程函数入门

  • 0

    开心

    开心

  • 0

    板砖

    板砖

  • 0

    感动

    感动

  • 0

    有用

    有用

  • 0

    疑问

    疑问

  • 0

    难过

    难过

  • 0

    无聊

    无聊

  • 0

    震惊

    震惊

编辑推荐
一、什么是信号 用过Windows的我们都知道,当我们无法正常结束一个程序时,可以用任务管理器强制结
文章结束给大家来个程序员笑话:[M] 一、fork系统调用 包含头文件 <sys/types.h> 和 <unis
用fork创建进程 除了进程0,其它所有的进程都是fork产生的。子进程是通过复制父进程的数据和代码产
用fork创建进程 除了进程0,其它所有的进程都是fork产生的。子进程是通过复制父进程的数据和代码产
1、fork函数 #include <unistd.h> pid_t fork(void); fork()用于创建一个新的process(进程)
1、wait和waitpid函数 #include <sys/types.h> #include <sys/wait.h> pid_t wait(int
最近一直在研究进程子进程之类的问题,现在正好有机会和大家共享一下. 一、进程间通信 每个进程各自
1. 概念: 子进程 父进程ppid 前台进程 后台进程 进程状态 2. 进程管理命令: 2.1 用户信息:w (lo
1. 概念: 子进程 父进程ppid 前台进程 后台进程 进程状态 2. 进程管理命令: 2.1 用户信息:w (lo
进程如何工作 launch init 程序(pid=1) init run shell scripts(located in /etc),start all the
版权所有 IT知识库 CopyRight © 2009-2015 IT知识库 IT610.com , All Rights Reserved. 京ICP备09083238号