操作系统导论-课后作业-ch5

关于man的使用

man  系统参考手册
man n name   在系统手册第n章查看name

1.

代码:

#include 
#include 
#include 
#include 

int main() {
    int x = 100;
    int rc = fork();
    if (rc == -1) {
        fprintf(stderr, "fork failed\n");
    } else if (rc == 0) {
        printf("child pid: x = %d\n", x);
    } else {
        wait(NULL);
    }
    return 0;
}

输出:
在这里插入图片描述
子进程会保持和父进程一样的值100,当子进程和父进程都改变x的值时,变量会各自单独保持一份互不影响,相互隔离。

2.

#include 
#include 
#include 
#include 
#include 
#include 
#include 

int main(int argc, char* argv[]) {
    int fd = open("./tmp.txt", O_CREAT | O_APPEND | O_RDWR, S_IRWXU);
    int rc = fork();
    if (rc == -1) {
        fprintf(stderr, "fork failed\n");
    } else if (rc == 0) {
        int i;
        for (i = 0; i < atoi(argv[1]); i++) write(fd, "child\n", 6);
    } else {
        int i;
        for (i = 0; i < atoi(argv[1]); i++) write(fd, "parent\n", 7);
        wait(NULL);
        close(fd);
    }
    return 0;
}

结果如下:
操作系统导论-课后作业-ch5_第1张图片
1次并没有发现并发问题,试过1000次也没什么问题

3.

可以使用vfork来做到等待子进程结束,具体可见系统手册:
在这里插入图片描述

#include 
#include 
#include 
#include 

int main() {
    int rc = vfork();
    if (rc == -1) {
        fprintf(stderr, "fork failed\n");
    } else if (rc == 0) {
        printf("hello\n");
    } else {
        printf("goodbye\n");
    }
    return 0;
}

另一种实现方式:

#include 
#include 
#include 
#include 
#include 

int flag = 0;

int main() {
    int rc = vfork();
    if (rc == -1) {
        fprintf(stderr, "fork failed\n");
    } else if (rc == 0) {
        printf("hello\n");
        flag = 1;
        exit(1);
    } else {
        while(flag == 0);
        printf("goodbye\n");
        wait(NULL);
    }
    return 0;
}

最终输出如下:
操作系统导论-课后作业-ch5_第2张图片

4.

#include 
#include 
#include 
#include 
#include 

int main() {
    int i; 
    for (i = 1; i <= 6; ++i) {
        int rc = fork();
        if (rc == -1) {
            fprintf(stderr, "fork failed\n");
            exit(1);
        } else if (rc == 0) {
            char* path = "/bin/ls";
            char* pro = "ls";
            char* target = ".";
            char* ev[] = {pro, target, NULL};
            switch (i)
            {
            case 1:
                execl(path, pro, target, NULL);
                break;
            case 2:
                execle(path, pro, target, NULL);
                break;
            case 3:
                execlp(pro, pro, target, NULL);
                break;
            case 4:
                execv(path, ev);
                break;
            case 5:
                execvp(pro, ev);
                break;
            case 6:
                execvpe(pro, ev);
                break;
            default:
                break;
            }
        } else {
            wait(NULL);
        }
    }
    return 0;
}

结果如下:
操作系统导论-课后作业-ch5_第3张图片

5.

#include 
#include 
#include 
#include 
#include 

int main() {
    int rc = vfork();
    if (rc == -1) {
        fprintf(stderr, "fork failed\n");
    } else if (rc == 0) {
        wait(NULL);
        printf("child pid is %d\n", getpid());
        exit(1);
    } else {
        int result = wait(NULL);
        printf("the return value is %d\n", result);
        exit(1);
    }
    return 0;
}

在这里插入图片描述
从上图中可见,wait返回的是子进程的进程号,而子进程中使用wait并不会发生什么,它会等待子进程自己的子进程结束。

6.

在这里插入图片描述
同样是返回pid,但是waitpid传入的参数不同,需要传入子进程的id、状态参数以及额外的选项。

#include 
#include 
#include 
#include 
#include 

int main() {
    int rc = vfork();
    if (rc == -1) {
        fprintf(stderr, "fork failed\n");
    } else if (rc == 0) {
        printf("child pid is %d\n", getpid());
        exit(1);
    } else {
        int result = waitpid(rc, NULL, 0);
        printf("the return value is %d\n", result);
        exit(1);
    }
    return 0;
}

结果如下图所示:
在这里插入图片描述

7.

#include 
#include 
#include 
#include 
#include 
#include 

int main() {
    int rc = fork();
    if (rc == -1) {
        fprintf(stderr, "fork failed\n");
    } else if (rc == 0) {
        close(STDOUT_FILENO);
        int res = printf("output something\n");
        fprintf(stderr, "%d\n", res);
        res = fflush(stdout);
        fprintf(stderr, "%d %s\n", res, strerror(errno));
    } else {
        wait(NULL);
    }
    return 0;
}

在这里插入图片描述
会把数据先写在缓存块内,具体可参考:在关闭stdout之后调用printf会发生什么?

8.

#include 
#include 
#include 
#include 

int main() {
    int fds[2];
    pipe(fds);
    int rc = fork();
    if (rc == -1) {
        fprintf(stderr, "fork failed\n");
    } else if (rc == 0) {
        close(STDOUT_FILENO);
        close(fds[1]);
        dup(fds[0]);
        close(fds[0]);
    }
    rc = fork();
    if (rc == -1) {
        fprintf(stderr, "fork failed\n");
    } else if (rc == 0) {
        close(STDIN_FILENO);
        close(fds[1]);
        dup(fds[1]);
        close(fds[1]);
        printf("hello\n");
    }
    close(fds[1]);
    close(fds[0]);
    wait(NULL);
    return 0;
}

结果如下图所示:
在这里插入图片描述

你可能感兴趣的:(#,操作系统导论,c语言,开发语言)