CS:APP 第8章 异常控制流 作业

8.9

进程对 并发?
AB
AC
AD
BC
BD
CD

8.10

A

fork

B

execvelongjmp

C

setjmp

8.11

4

8.12

8

8.13

x=4
x=3
x=2

8.14

3

8.15

5

8.16

counter = 2

8.17

三种可能性。

1
Hello
0
1
Bye
2
Bye
2
Hello
1
0
Bye
2
Bye
3
Hello
1
Bye
0
2
Bye

8.18

A,C,E

8.19

8.20

#include 
using namespace std;

int main(int argc, char* argv[], char* envp[])
{
    execve("/bin/ls", argv, envp);
}

不明白意义何在,练习如何使用execve么。。

8.21

abcbac

8.22

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

void unix_error(char* msg){
    fprintf(stderr, "%s : %s\n", msg, strerror(errno));
}

pid_t Fork(){
    pid_t pid;
    if((pid = fork()) < 0)
        unix_error("Fork error");
    return pid;
}

int mysystem(char* command){
    pid_t pid = Fork();
    if(pid){
        int status;
        wait(&status);
        if(WIFEXITED(status))
            return WEXITSTATUS(status);
        if(WIFSIGNALED(status))
            return WTERMSIG(status);
    }else{
        char* argv[] = {"/bin/sh", "-c", command, NULL};
        execve("/bin/sh", argv, NULL);
    }

}

int main(int argc, char* argv[], char* envp[])
{
    printf("exit code: %d\n", mysystem(argv[1]));
    fflush(stdout);
}

mac上好像ctrl+c无法触发,通过资源监视器杀进程可以触发非正常退出的分支。

8.23

信号量不会排队,当子进程给父进程发送信号时,第一个信号会被接受并且处理,第二个信号会被记录并且等待第一个信号处理完成,其他的信号都会被简单地丢弃。
所以正如教材前面所说的,不能使用信号量对其他进程中的某些东西计数。

8.24

#include "csapp.h"
#define N 2

int main(){
    int status, i;
    pid_t pid;
    /* Parent creates N children */
    for(i = 0; i < N; i++)
        if((pid = Fork()) == 0){
            int* p = 0x0;
            *p = 1;
            exit(0);
        }
    /* Parent reaps N children in no particular order */
    while((pid = waitpid(-1, &status, 0)) > 0){
        if(WIFEXITED(status))
            printf("child %d terminated normally with exit status = %d\n", pid, WEXITSTATUS(status));
        else if(WIFSIGNALED(status)){
            Sio_puts("child ");
            Sio_putl(pid);
            psignal(SIGSEGV, " terminated by signal 11");
        }
    }
    /* The only normal termination is if there are no more children */
    if(errno != ECHILD)
        unix_error("waitpid error");
    exit(0);
}
运行输出:
child 42018 terminated by signal 11: Segmentation fault
child 42019 terminated by signal 11: Segmentation fault

一开始没看懂题目意思,看懂后阅读psignal相关资料就可以完成,注意使用printf会出问题,因为printf并不是安全的,这里使用的是SioputsSioputl,也可以使用sprintf先写到缓冲区然后利用psignal进行输出。

8.25

#include "csapp.h"

sigjmp_buf buf;

void sigchld_handler(int sig){
    siglongjmp(buf, 1);
}

char* tfgets(char* str){
    if(sigsetjmp(buf, 1))
        return NULL;
    pid_t pid;
    if(signal(SIGCHLD, sigchld_handler) == SIG_ERR)
        unix_error("set SIGCHLD error");
    if((pid = Fork()) == 0){
        sleep(5);
        exit(0);    
    }else{
        return gets(str);
    }
}

int main(){
    char buf[256];
    puts(tfgets(buf));
}

首先得开一个子进程对五秒时间进行计数,如果子进程成功返回说明超时应该返回NULL,不然直接返回gets的结果就行。
所以父进程应该直接调用gets满足不超时的情况,问题在于超时后父进程捕捉到子进程结束时的仍在等待gets,而signal handler只能返回到当前指令无法对流程进行控制,这时候就应该使用非本地跳转返回到注册地进行处理。
理论上感觉goto也是可以的,由于实用性不高没有进行尝试。

8.26

其实就是shell lab,等待完成中。

你可能感兴趣的:(CS:APP 第8章 异常控制流 作业)