[第八章] 深入理解计算机系统第三版 家庭作业参考答案

8.9

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

8.10

A. fork
B. longjmp execve
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

hello 0 1 Bye 2 Bye
hello 1 0 Bye 2 Bye
hello 1 Bye 0 2 Bye

8.18

BD

8.19

2^n

8.20

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

void unix_error(char *msg) /* Unix-style error */
{
    fprintf(stderr, "%s: %s\n", msg, strerror(errno));
    exit(0);
}

void Execve(const char *filename, char *const argv[], char *const envp[]) 
{
    if (execve(filename, argv, envp) < 0)
	unix_error("Execve error");
}

int main(int argc, char **argv, char **env) {
	Execve("/bin/ls", argv, env);
	return 0;
}


8.21

abc 或 bac

8.22

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#define MAXARGS 128
#define MAXLINE 8192  /* Max text line length */

extern char **environ; /* Defined by libc */
						  /* Linux C中environ 变量是一个char** 类型,存储着系统的环境变量 */

void unix_error(char *msg) /* Unix-style error */
{
    fprintf(stderr, "%s: %s\n", msg, strerror(errno));
    exit(0);
}

void app_error(char *msg) /* Application error */
{
    fprintf(stderr, "%s\n", msg);
    exit(0);
}

pid_t Wait(int *status) 
{
    pid_t pid;

    if ((pid  = wait(status)) < 0)
	unix_error("Wait error");
    return pid;
}

char *Fgets(char *ptr, int n, FILE *stream) 
{
    char *rptr;

    if (((rptr = fgets(ptr, n, stream)) == NULL) && ferror(stream))
	app_error("Fgets error");

    return rptr;
}

/* parseline - Parse the command line and build the argv array */
int parseline(char *buf, char **argv) 
{
    char *delim;         /* Points to first space delimiter */
    int argc;            /* Number of args */
    int bg;              /* Background job? */

    buf[strlen(buf)-1] = ' ';  /* Replace trailing '\n' with space */
    while (*buf && (*buf == ' ')) /* Ignore leading spaces */
	buf++;

    /* Build the argv list */
    argc = 0;
    while ((delim = strchr(buf, ' '))) {
	argv[argc++] = buf;
	*delim = '\0';
	buf = delim + 1;
	while (*buf && (*buf == ' ')) /* Ignore spaces */
            buf++;
    }
    argv[argc] = NULL;
    
    if (argc == 0)  /* Ignore blank line */
	return 1;

    /* Should the job run in the background? */
    if ((bg = (*argv[argc-1] == '&')) != 0)
	argv[--argc] = NULL;

    return bg;
}

pid_t Fork(void) 
{
	pid_t pid;

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

int mysystem(char *command) {
	char *Argv[MAXARGS];
	int status;
	
	if(Fork() == 0) {
		parseline(command, Argv);
		for(int i = 0; i < MAXARGS; i++) {
			if(Argv[i]==NULL) {
				break;
			}
		}
		execve("/bin/sh", Argv, environ);
	}

	Wait(&status); 	/*等待子进程结束*/
	return WEXITSTATUS(status);	
}

int main(int argc, char **argv, char **env) {
	char str[12] = "/bin/sh -c ";
	char command[MAXLINE];
	char temp[MAXLINE-12];
	printf("\033[1;32m>\033[0m ");
	while(Fgets(temp, MAXLINE-12, stdin)) {
		strcpy(command, str);
		strcat(command, temp);
		printf("\033[1;32m mysystem 返回值为 %d \n\033[0m", mysystem(command));
		printf("\033[1;32m\n>\033[0m ");
	}
	return 0;
}

我并没有使用 “csapp.h” 头文件,而是用到什么就复制出什么,一方面可以清楚被封装函数的调用方法,另一方面可以学习作者是如何对函数进行封装的。
我做的有些麻烦,虽然使用了 parseline 函数,但是我的代码只支持不带参数的 command,比如 “/bin/sh ls -a”,就只能识别到 “/bin/sh ls”,可以修改 parseline 函数,不过我懒 (ಥ _ ಥ)

对于几种不同的输入,有不同的返回值:

USER@NAME:~# ./mysystem
> ls
123.py		 公共		模板
.........
 
mysystem 返回值为 0 

> ./exit12
 
mysystem 返回值为 12 

> lllll
/bin/sh: 1: lllll: not found
 
mysystem 返回值为 127 

exit12 程序非常简单,只有四行:

#include 
#include 
int main() {
	exit(12);
}

8.23

一个进程的待处理信号不会排队,只会被丢弃。

8.24

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

#define N 2
const char CONSTINT[10] = "HAHA";	//只读常量

void unix_error(char *msg) /* Unix-style error */
{
    fprintf(stderr, "%s: %s\n", msg, strerror(errno));
    exit(0);
}

pid_t Waitpid(pid_t pid, int *iptr, int options) 
{
    pid_t retpid;

    if ((retpid  = waitpid(pid, iptr, options)) < 0) 
	unix_error("Waitpid error");
    return(retpid);
}


pid_t Fork(void) 
{
    pid_t pid;

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

int main() 
{
    int status, i;
    pid_t pid;

    for (i = 0; i < N; i++)                       
		if ((pid = Fork()) == 0) { /* Child */     
			scanf("%s", &CONSTINT); 		//访问只读常量
			exit(100 + i);                   
		}    

    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)) {
			//const char *s;	
			printf("child %d terminated by signal %d:", pid, WTERMSIG(status));
			fflush(stdout);
			psignal(WTERMSIG(status), NULL);
		}
    }

    if (errno != ECHILD)                          
	unix_error("waitpid error");

    exit(0);
} 
USER@NAME:~# gcc -o P8-24 P8-24.c 
USER@NAME:~# ./P8-24
123123
child 11345 terminated by signal 11: Segmentation fault
22
child 11344 terminated by signal 11: Segmentation fault

8.25

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

sigjmp_buf buf;

unsigned int Alarm(unsigned int seconds) {
    return alarm(seconds);
}

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

char *tfgets(char *s, int size, FILE *stream) {
	signal(SIGALRM, handler);

	if (!sigsetjmp(buf, 1)) {
        Alarm(5);
		fgets(s, size, stream);
    }
    else {
		return NULL;
	}
	
	signal(SIGALRM, SIG_DFL);
	return s;
}

int main() 
{
    while(1) {
		char s[50];
		char *temp = tfgets(s, 50, stdin);

		if(temp == NULL) {
			printf("超时\n\n");
		} else {
			printf("输入的字符串是:%s\n", temp);
		}
    }
    exit(0); 
}

8.26

你可能感兴趣的:(CSAPP)