Operating Systems Principles and practice 2nd 3Ch Exercises

Source: Internet
Author: User


Preface:most of the answers below is written by myself---only instructors is given access to the exercise solutions. If you find anything wrong, please let me know so that I can correct them, thank you!



1. Can UNIX fork return an error? Why or?

Note:you can answer this question by looking at the manual page for fork, but before you did that, think on what the FO RK system call does. If You were designing this call, would do you need-to-allow fork-to-return an error?


Yes. Because we need to ensure the parent process notified if this system call fails, and returning a error directly is one WA Y to achieve.

According to the mans page of in fork(2) Ubuntu 18.04.1:

On failure, 1 was returned in the parent, No child process was created, and errno is set appropriately.



2. Can UNIX exec return an error? Why or?

Note:you can answer this question by looking on the manual page for exec, but before you does that, think on what the ex EC system call does. If You were designing this call, would you need to allow it to return an error?


Yes. Because when a process fails to call exec() , we must ensure it notified to do something about this exception, and returning An error directly is one of the "the" to achieve.

According to the mans page of in execve(2) Ubuntu18.04.1:

On Error-1 are returned, and errno is set appropriately.



3. What happens if we run the following program on UNIX?
main(){    while (fork() >= 0)        ;}


This is called a fork bomb, which are a denial-of-service attack where in a process continually replicates itself To deplete available system resources, slowing down or crashing the system due to resource starvation.

After I run this bomb in Ubuntu 18.04.1 (VirtualBox), it seems like the process-resources is being exhausted and other p Rograms can not be started:



4. Explain What must happen for UNIX wait to return immediately (and successfully).


According to the manual pages of FreeBSD, in return from a successful call wait() , the status area contains information Abo UT the process that reported a status change would be set. And in the case of a terminated child, performing a wait() allows the system to release the resources associated with the C Hild.



The fifth question is meaningless.



6. What happens if you run "exec csh" in a UNIX shell? Why?


The shell would be replaced csh with, but the process (ID) preserved:



7. What happens if you run the "exec ls" in a UNIX shell? Why?


The shell would be replaced and the program with ls same process, but since ls was not a interactive program, the Te rminal window would close instantly.



8. How many processes was created if the following program is run?
void forkthem(int n){    if (n > 0){        fork();        forkthem(n-1);    }}main(int argc, char ** argv){    forkthem(5);}


2^5 = 32



9. Consider the following program:


main (int argc, char ** argv) {    int child = fork();    int x = 5;        if (child == 0){        x += 5;    } else {        child = fork();        x += 10;        if(child) {            x+= 5;        }    }}

How many different copies of the variable x is there? What is their values when their process finishes?


There'll be three different copies of the variable x:5+5=10, 5+10=15, 5+10+5=20.



What is the output of the following programs? (try to solve the problem without compiling and running the programs.)
// Program 1main() {    int val = 5;    int pid;        if (pid = fork())        wait(pid);    val++;    printf("%d\n", val);    return val;}//Program 2main(){    int val = 5;    int pid;    if (pid = fork())        wait(pid);    else        exit(val);    val++;    printf("%d\n", val);    return val;}


Program 1:6\n6\n

Program 2:6\n



Implement a simple Linux shell in C capable of executing a sequence of programs that communicate through a pipe. For example, if the user types ls | WC, your program should fork off the programs, which together would calculate the number of files in the directory. For this, you'll need to use several of the Linux system calls described in this chapter:fork, exec, open, close, pipe, Dup2, and wait. Note:you'll to replace stdin and stdout in the child process with the pipe file descriptors; That's the role of Dup2.


I have implemented a shell which supports foreground and background tasks, as well as job control when I read the CSAP P 3eCode and descriptions here (Chinese), so I'll just improve it with pipeline.

The part of changed code:

/* * Find_second_argv_in_pipe-find the ARGV for the second program in * single-pipe command * * If no pipe symbol fin  D, return NULL, else return the second argv */char * * Find_second_argv_in_pipe (char *argv[]) {for (int i = 0; Argv[i]! = NULL;        i++) {if (!strcmp (Argv[i], "|"))            {Argv[i] = NULL;        Return &argv[i+1]; }} return NULL;} /* eval-evaluate the command line, the user has just typed in * * If the user has requested a built-in command (QU It, jobs, BG or FG) * then execute it immediately. Otherwise, fork a child process and * run the job in the context of the child.  If the job is running in * The foreground, wait for it to terminate and then return. Note: * Each child process must has a unique process group ID so, our * background children don ' t receive SIGINT (SIG TSTP) from the kernel * if we type ctrl-c (ctrl-z) at the keyboard.    * *2018.10.14:single Pipe is supported now */void eval (char *cmdline) {Char *argv[maxargs];    char **argv2 = NULL;    int Bg_flag; Bg_flag = ParseLine (CmdLine, argv); /* True if the user has requested a BG job and False if the user has requested a FG job.    */argv2 = Find_second_argv_in_pipe (argv);    if (Builtin_cmd (argv, cmdline))/* Built-in command */{return;        } else/* Program (file) */{pid_t pid;        sigset_t Mask, prev;        Sigemptyset (&mask);        Sigaddset (&mask, SIGCHLD); Sigprocmask (Sig_block, &mask, &prev); /* Block SIG_CHLD */int pipefd[2];        /* Pipefd[0] refers to the read end of the pipe. Pipefd[1] refers to the write end of the pipe. */if (Access (argv[0], F_OK)/* * Does not fork and addset!            */{fprintf (stderr, "%s:command not found\n", argv[0]);        Return             if (ARGV2)/* Single PIPE command */{if (Access (argv2[0], F_OK) */* Do not fork and addset! */ {fprintf (stderr, "%s: Command not found\n ", argv2[0]);            Return                } if (pipe (PIPEFD)) {perror ("Failed to creat pipe file");            Return }} if ((Pid=fork ()) = = 0)/* child1 */{Sigprocmask (Sig_setmask, &prev, NULL);/* UN                    Block SIG_CHLD */if (!setpgid (0, 0)) {if (ARGV2) {                        if ((Pid=fork ()) = = 0)/* child2 */{if ((Dup2 (pipefd[0], Stdin_fileno) ==-1))                            {perror ("Failed to dup2 with PROGRAM2 for pipe operation");                        _exit (exit_failure);                        } close (pipefd[0]); Close (pipefd[1]); if (Execve (argv2[0], argv2, environ)) {fprintf (stderr, "%s:failed to E                            Xecve\n ", argv2[0]); _exit(exit_failure);                        }} if ((Dup2 (pipefd[1], Stdout_fileno) ==-1) {                        Perror ("Failed to dup2 with PROGRAM1 for pipe operation");                    _exit (exit_failure);                } close (pipefd[0]); Close (pipefd[1]); } if (Execve (argv[0], argv, environ)) {fprintf (stderr, "%s:failed to ex                    Ecve\n ", argv[0]);                _exit (exit_failure);  }/* Context changed */} else {fprintf (stderr, "Failed to                Invoke Setpgid (0, 0) \ n ");            _exit (exit_failure);                }} else if (PID > 0)/* tsh */{if (!bg_flag)/* EXEC foreground */{                Fg_pid = pid;                fg_pid_reap = 0;                AddJob (Jobs, PID, FG, CmdLine); Sigprocmask(Sig_setmask, &prev, NULL);            /* Unblock SIG_CHLD */WAITFG (PID);                } else/* EXEC background */{addjob (jobs, PID, BG, CmdLine); Sigprocmask (Sig_setmask, &prev, NULL);            /* Unblock SIG_CHLD */printf ("[%d] (%d)%s", Maxjid (Jobs), PID, cmdline);  }/* DONT ' T forget to close the pipefd in TSH process otherwise the second program would stall output            until TSH exits */close (pipefd[0]); Close (pipefd[1]);        Return        } else {unix_error ("Failed to Fork Child"); }} return;




Extend the shell implemented above to support foreground and background tasks, as well as job control:suspend, resume , and kill.


Please refer to the code above.

Operating Systems Principles and practice 2nd 3Ch Exercises

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.