ostep-进程API

也可以称为系统调用。

fork

在unix中,创建新的进程可以使用fork。

#include "syscalls.h"

int main(int argc,char *argv[])
{
    printf("hello,world (pid:%ld)\n",(long)getpid());
    long rc = fork();
    if(rc < 0)
    {
        fprintf(stderr,"forl failed\n");
        exit(1);
    } else if(rc == 0){
        printf("hello,I am child(pid:%ld)->(forkReturn:%ld)\n",(long)getpid(),rc);
    } else{
        printf("hello,I am parent(pid:%ld)->(forkReturn:%ld)\n",(long)getpid(),rc);
    }

    return 0;
}

输出就像这样:

hello,world (pid:28244)
hello,I am parent(pid:28244)->(forkReturn:28245)
hello,I am child(pid:28245)->(forkReturn:0)

关于fork创建的子进程,有几点需要知道。首先,子进程几乎是父进程的一个精确的拷贝,就是二者几乎完全一样。所以,子进程不需要从main开始运行。
子进程有自己的私有PC,私有地址空间,自己的寄存器等等。当父进程收到子进程的PID时,子进程得到一个0的返回值。这个返回值是指fork的返回值。
也就是说,fork返回给父进程子进程的PID,子进程得到的是0.具体可查看代码输出。
以上代码的输出顺序是不固定的。书上说是不固定的,但是我试了好多次都是固定的,可能,虽然我也认同不是固定的。

wait

等待子进程完成。

#include "syscalls.h"

int main(int argc,char *argv[])
{
    printf("hello,world (pid:%ld)\n",(long)getpid());
    long rc = fork();
    if(rc < 0)
    {
        fprintf(stderr,"forl failed\n");
        exit(1);
    } else if(rc == 0){
        printf("hello,I am child(pid:%ld)->(forkReturn:%ld)\n",(long)getpid(),rc);
    } else{
        int wc = wait(NULL);
        printf("hello,I am parent(pid:%ld)->(forkReturn:%ld)->(waitReturn:%d)\n",(long)getpid(),rc,wc);
    }

    return 0;
}

输入如下:

hello,world (pid:28906)
hello,I am child(pid:28907)->(forkReturn:0)
hello,I am parent(pid:28906)->(forkReturn:28907)->(waitReturn:28907)

wait的返回值是子进程pid。
输出顺序固定。

exec

这个系统调用是用来运行其他程序的,创建基于其他程序的进程。

#include "syscalls.h"

int main(int argc,char *argv[])
{
    printf("hello,world (pid:%ld)\n",(long)getpid());
    long rc = fork();
    if(rc < 0)
    {
        fprintf(stderr,"forl failed\n");
        exit(1);
    } else if(rc == 0){
        char *myargs[3];
        myargs[0] = strdup("wc");
        myargs[1] = strdup("ostep_exec.c");
        myargs[2] = NULL;

        execvp(myargs[0],myargs);

        printf("this should not print out");
        printf("hello,I am child(pid:%ld)->(forkReturn:%ld)\n",(long)getpid(),rc);
    } else{
        int wc = wait(NULL);
        printf("hello,I am parent(pid:%ld)->(forkReturn:%ld)->(waitReturn:%d)\n",(long)getpid(),rc,wc);
    }

    return 0;
}

输出如下:

hello,world (pid:29268)
 30  66 767 ostep_exec.c
hello,I am parent(pid:29268)->(forkReturn:29269)->(waitReturn:29269)

exec的调用重新初始化了地址空间,包括堆栈等。以及代码和静态数据。
但是exec的pid和fork得到的pid是一样的。

tips:调用fork部分的实例代码

#include "syscalls.h"

int main(int argc,char *argv[])
{
    printf("hello,world (pid:%ld)\n",(long)getpid());
    long rc = fork();
    if(rc < 0)
    {
        fprintf(stderr,"forl failed\n");
        exit(1);
    } else if(rc == 0){
        char *myargs[3];
        myargs[0] = strdup("./process");
        myargs[1] = NULL;
        myargs[2] = NULL;

        execvp(myargs[0],myargs);

        printf("this should not print out");
        printf("hello,I am child(pid:%ld)->(forkReturn:%ld)\n",(long)getpid(),rc);
    } else{
        int wc = wait(NULL);
        printf("hello,I am parent(pid:%ld)->(forkReturn:%ld)->(waitReturn:%d)\n",(long)getpid(),rc,wc);
    }

    return 0;
}

你可能感兴趣的:(ostep-进程API)