操作系统导论习题解答(5. Process API)

0. installing and using of Cygmin

Since Cygwin was installed at the request of the teacher when taking the basic computer class, I will not introduce it here.

1. The fork() System Call

// p1.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main(int argc, char *argv[]) {
    printf("hello world (pid:%d)\n", (int) getpid());
    int rc = fork();
    if (rc < 0) {
    // fork failed
        fprintf(stderr, "fork failed\n");
        exit(1);
    } else if (rc == 0) {
    // child (new process)
        printf("hello, I am child (pid:%d)\n", (int) getpid());
    } else {
        printf("hello, I am parent of %d (pid:%d)\n",
            rc, (int) getpid());
    }
    return 0;
}

在这里插入图片描述
The PID is different each time, which is normal.

2. The wait() System Call

// p2.c
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/wait.h>

int main(int argc, char *argv[])
{
    printf("hello world (pid:%d)\n", (int) getpid());
    int rc = fork();
    if (rc < 0)
    // fork failed; exit
    {
        fprintf(stderr, "fork falied\n");
        exit(1);
    }
    else if (rc == 0)
    // child (new process)
    {
        printf("hello, I am child (pid:%d)\n", (int) getpid());
    }
    else 
    // parent goes down this path (main)
    {
        int rc_wait = wait(NULL);
        printf("hello, I am parent of %d (rc_wait:%d) (pid:%dn",
            rc, rc_wait, (int) getpid());
    }
    return 0;
}

在这里插入图片描述
The child will always print first.

3. The exec() System Call

// p3.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/wait.h>

int main(int argc, char *argv[]) {
    printf("hello world (pid:%d)\n", (int) getpid());
    int rc = fork();
    if (rc < 0) { // fork failed; exit
        fprintf(stderr, "fork failed\n");
        exit(1);
    } else if (rc == 0) { // child (new process)
        printf("hello, I am child (pid:%d)\n", (int) getpid());
        char *myargs[3];
        myargs[0] = strdup("wc"); // program: "wc" (word count)
        myargs[1] = strdup("p3.c"); // argument: file to count
        myargs[2] = NULL; // marks end of array
        execvp(myargs[0], myargs); // runs word count
        printf("this shouldn’t print out");
    } else { // parent goes down this path (main)
        int rc_wait = wait(NULL);
        printf("hello, I am parent of %d (rc_wait:%d) (pid:%d)\n",
        rc, rc_wait, (int) getpid());
    }
    return 0;
}

在这里插入图片描述
The exec system call does not create a new process, but replaces the content of the original process context. The code segment, data segment, and stack segment of the original process are replaced by the new process.

4. Why? Motivating The API

// p4.c
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#include<fcntl.h>
#include<sys/wait.h>

int main(int argc, char *argv[])
{
    int rc = fork();
    if (rc < 0)
    {
        // fork failed
        fprintf(stderr, "fork failed\n");
        exit(1);
    }
    else if (rc == 0)
    {
        // child: redirect standard output to a file
        close(STDERR_FILENO);
        open("./p4.output", O_CREAT | O_WRONLY | O_TRUNC, S_IRWXU);

        // now exec "wc"...
        char *myargs[3];
        myargs[0] = strdup("wc");   // program: wc (word count)
        myargs[1] = strdup("p4.c"); // arg: file to count
        myargs[2] = NULL;           // mark end of array
        execvp(myargs[0], myargs);  // runs word count
    }
    else
    {
        // parent goes down this path (main)
        int rc_wait = wait(NULL);
    }
    return 0;
}

在这里插入图片描述

5. Process Control And Users

在这里插入图片描述

6. Homework(Simulation)

This simulation homework focuses on fork.py, a simple process creation simulator that shows how processes are related in a single “familial” tree. Read the relevant README for details about how to run the simulator.

Question & Answer

1

在这里插入图片描述
test: python forl.py -s 10python fork.py -s 10
verification: python fork.py -s 10 -c在这里插入图片描述

2

在这里插入图片描述
test: python fork.py -a 100 -f 0.10.1
verification: python fork.py -a 100 -f 0.1 -c在这里插入图片描述

3

在这里插入图片描述

在这里插入图片描述在这里插入图片描述
You can flip the question around with the -t flag, which allows you to view process tree states and then guess what action must have taken place.

4

在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述

5

在这里插入图片描述在这里插入图片描述在这里插入图片描述
You can use different random seeds (-s flag) or just don't specify one to get different randomly generated sequences.

6

在这里插入图片描述在这里插入图片描述在这里插入图片描述
You can try more.

7. Homework (Code)

在这里插入图片描述

Question & Answer

1

在这里插入图片描述

// p1.c
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>

int main(int argc, char *argv[])
{
    int x = 100;
    printf("hello world (pid:%d), x = %d\n", (int) getpid(), x);
    int rc = fork();
    if (rc < 0)
    {
        // fork failed
        fprintf(stderr, "fork failed\n");
        exit(1);
    }
    else if (rc == 0)
    {
        // child (new process)
        printf("hello, I am child (pid:%d), x = %d\n", (int) getpid(), x);
    }
    else
    {
        // parent goes down this path (main)
        printf("hello, I am parent of %d (pid:%d), x = %d\n",
            rc, (int) getpid(), x);
    }
    return 0;
}

在这里插入图片描述

2

在这里插入图片描述

// p2.c
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<fcntl.h>
#include<sys/wait.h>
#include<assert.h>

int main(int argc, char *argv[])
{
    printf("hello world (pid:%d)\n", (int) getpid());

    // open a file
    int fd = open("./openFile", O_WRONLY | O_CREAT | O_TRUNC, S_IRWXU);
    assert(fd > -1);  // open failed, exit

    int rc = fork();
    if (rc < 0)
    {
        // fork failed
        fprintf(stderr, "fork failed\n");
        exit(1);
    }
    else if (rc == 0)
    {
        // child: redirect standard outpupt to a file
        printf("hello, I am child (pid:%d)\n", (int) getpid());
        printf("fd = %d\n", fd);
    }
    else
    {
        // parent goes down this path (main)
        printf("hello, I am parent of %d (pid:%d)\n", rc, (int) getpid());
        printf("fd = %d\n", fd);
    }
    return 0;
}

在这里插入图片描述

3

在这里插入图片描述

// p3.c
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>

int main(int argc, char *argv[])
{
    printf("hello world (pid:%d)\n", (int) getpid());
    int rc = fork();
    if (rc < 0)
    {
        // fork failed
        fprintf(stderr, "fork failed\n");
        exit(1);
    }
    else if (rc == 0)
    {
        // child (new process)
        printf("hello, I am child (pid:%d)\n", (int) getpid());
    }
    else
    {
        // parent goes down this path (main)
        int rd = fork();
        if (rd == 0)
            printf("goodbye, I am parent (pid:%d)\n", (int) getpid());
    }
    return 0;
}

在这里插入图片描述

4

在这里插入图片描述

// p4.c
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#include<sys/wait.h>

int main(int argc, char *argv[])
{
    printf("hello world (pid:%d)\n", (int) getpid());
    int rc = fork();
    if (rc < 0)
    {
        // fork failed; exit
        fprintf(stderr, "fork failed\n");
        exit(1);
    }
    else if (rc == 0)
    {
        // child (new process)
        printf("hello, I am child (pid:%d)\n", (int) getpid());
        char *myargs[2];
        myargs[0] = strdup("/bin/ls");
        myargs[1] = NULL;
        execvp(myargs[0], myargs);
        printf("this shouldn't print out");
    }
    else
    {
        // parent goes down this path (main)
        int rc_wait = wait(NULL);
        printf("hello, I am parent of %d (rc_wait:%d) (pid:%d)\n", 
           rc, rc_wait, (int) getpid());
    }
    return 0;
}

在这里插入图片描述

5

在这里插入图片描述

// p5a.c wait() in the parent
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#include<sys/wait.h>

int main(int argc, char *argv[])
{
    printf("hello world (pid:%d)\n", (int) getpid());
    int rc = fork();
    if (rc < 0)
    {
        // fork failed; exit
        fprintf(stderr, "fork failed\n");
        exit(1);
    }
    else if (rc == 0)
    {
        // child (new process)
        printf("hello, I am child (pid:%d)\n", (int) getpid());
    }
    else
    {
        // parent goes down this path (main)
        int rc_wait = wait(NULL);
        printf("hello, I am parent of %d (rc_wait:%d) (pid:%d)\n", 
        rc, rc_wait, (int) getpid());
    }
    return 0;
}

在这里插入图片描述

// p5b.c wait() in the child
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#include<sys/wait.h>

int main(int argc, char *argv[])
{
    printf("hello world (pid:%d)\n", (int) getpid());
    int rc = fork();
    if (rc < 0)
    {
        // fork failed; exit
        fprintf(stderr, "fork failed\n");
        exit(1);
    }
    else if (rc == 0)
    {
        // child (new process)
        int rc_wait = wait(NULL);
        printf("hello, I am child (rc_wait:%d) (pid:%d)\n", rc_wait, (int) getpid());
    }
    else
    {
        // parent goes down this path (main)
        printf("hello, I am parent of %d (pid:%d)\n", rc, (int) getpid());
    }
    return 0;
}

在这里插入图片描述

6

在这里插入图片描述

// p6.c
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#include<sys/wait.h>

int main(int argc, char *argv[])
{
    printf("hello world (pid:%d)\n", (int) getpid());
    int rc = fork();
    if (rc < 0)
    {
        // fork failed; exit
        fprintf(stderr, "fork failed\n");
        exit(1);
    }
    else if (rc == 0)
    {
        // child (new process)
        printf("hello, I am child (pid:%d)\n", (int) getpid());
    }
    else
    {
        // parent goes down this path (main)
        /* pid_t waitpid(pid_t pid, int* status, int options);
         * if you are not familiar with this function, 
         * you can go to Baidu Baike, don’t be afraid of trouble.
        */
        waitpid(rc, NULL, WNOHANG);
        printf("hello, I am parent of %d (pid:%d)\n", rc, (int) getpid());
    }
    return 0;
}

在这里插入图片描述

7

在这里插入图片描述

// p7.c
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>

int main(int argc, char *argv[])
{
    printf("hello world (pid:%d)\n", (int) getpid());
    int rc = fork();
    if (rc < 0)
    {
        // fork failed; exit
        fprintf(stderr, "fork failed\n");
        exit(1);
    }
    else if (rc == 0)
    {
        // child (new process)
        close(STDOUT_FILENO);
        printf("hello, I am child (pid:%d)\n", (int) getpid());
    }
    else
    {
        // parent goes down this path (main)
        printf("hello, I am parent of %d (pid:%d)\n", rc, (int) getpid());
    }
    return 0;
}

在这里插入图片描述

8

在这里插入图片描述pipe函数详解

// p8.c
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#include<errno.h>

int main(int argc, char *argv[])
{
    int fd[2];
    /* fd[0] points to the read port of the pipe
     * fd[1] points to the write port of the pipe 
    */
    int ret = pipe(fd);
    if (ret == -1)
    {
        perror("pipe error\n");
        exit(1);
    }
    int rc = fork();
    if (rc < 0)
    {
        // fork failed; exit
        fprintf(stderr, "fork failed\n");
        exit(1);
    }
    else if (rc == 0)
    {
        // child (new process)
        close(fd[0]);
        char *child = "I am child";
        for (int i = 0; i < 5; i++)
        {
            write(fd[1], child, strlen(child) + 1);
            sleep(2);
        }
    }
    else
    {
        // parent goes down this path (main)
        close(fd[1]);
        char msg[50];
        for (int i = 0; i < 5; i++)
        {
            memset(msg, '\0', sizeof(msg));
            ssize_t s = read(fd[0], msg, sizeof(msg));
            if (s > 0)
                msg[s - 1] = '\0';
            printf("%s\n", msg);
        }
    }
    return 0;
}

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值