Academic Integrity: tutoring, explanations, and feedback — we don’t complete graded work or submit on a student’s behalf.

1. In apue.3e/environ a. Compile & link doatexit.c i. Run doatexit ii. Capture o

ID: 665987 • Letter: 1

Question

1. In apue.3e/environ a. Compile & link doatexit.c i. Run doatexit ii. Capture output b Try adding two more exits i. Make acopy 1cp doatexit.c doatexit2.c 2. check permissions for new file PS1 OR nor-X-Ra il. Compile iii. Run v. Capture output radiieDevelop:-/CS510/apue. 3e/environs .Idoatexit2 main is done first exit handler second exit handler third exit handler fourth exit handler fifth exit handler 2. In apue.3e/environ Compile & link echoarg.c L Run echoarg a. Capture output b. How do you increase the number of arguments? 3. In apue.3e/exercises a. Compile & link zombie.c L Run zombie Capture output Any rombie processes? 2. Wait twenty minutes " 1. Rerun zombie a. b. Capture output Any zombie processes? 2. If things changed, why? b. Compile & link vfork3 i. Run vfork3 1. Capture output What's the structure address? 2. 4. In apue.3e/proc a. Compile & link fork1 l Run fork ii. Capture output b. Compile & link timesi i. Run times1 leg:Jruntimes1 Is] ii. Capture output c. Compile & link wait Run wait1 ii. Capture output ii. Where do the Signals' come from? radi ieDevelop:-/CS510/apue.3e/proc ./wait1 normal termination, exit status-7 abnornal termination, signal number6 abnormal ternination, signal number- radi i@Develop:-/CS510/apue. 3e/proes

Explanation / Answer

#include "apue.h"
static void my_exit1(void);
static void my_exit2(void);
int main(void)
{
if (atexit(my_exit2) != 0)
err_sys("can't register my_exit2");
if (atexit(my_exit1) != 0)
err_sys("can't register my_exit1");
if (atexit(my_exit1) != 0)
err_sys("can't register my_exit1");
printf("main is done ");
return(0);
}
static void my_exit1(void)
{
printf("first exit handler ");
}
static void my_exit2(void)
{
printf("second exit handler ");
}
#include "../../apue.h"
int main(int argc, char *argv[])
{
int i;
for (i=0; i<argc; i++)
printf("argv[%d]: %s ", i, argv[i]);
printf(" ");
exit(0);
}
A zombie process is just a pid, an exit status, and some accounting information that stays around until a parent uses one of the wait family of system calls to get its final status. Until a parent calls wait the child's process ID must stay marked as used so that no other process can be assigned it. If another process were to get assigned a recycled pid it would be difficult to tell the difference between it and previous processes that had that same pid. Once wait is called by the parent and returns a final exit status it can be assumed that no one will go looking for the child at that pid again, so the pid may now be reused. (I think on Linux if a parent leaves SIGCHLD as SIG_IGN the kernel will not keep zombies around, but that re-registering SIGCHLD's disposition as SIG_IGN does not have the same effect)
-- know that the kernel keeps (PID,termination status, resource usage information) for zombie process what's the meaning of "resource usage information"
Some of this information is what running a program as:
time my_program
will report. These values are usually reported in the siginfo structure for SIGCHLD (which isn't exactly a call to wait) but also available from a call to the waitid form of systme call (on some systems). Look at man sigaction for info about this structure.
-- how zombie's PPID() = 1 and it still zombie , (init reaps Zombies because it wait() by default)
A zombie whose ppid = 1 should not stay a zombie for very long because init should reap it pretty quickly. A process will remain a zombie from a point soon after it dies (either via exit or by an unhanded signal that kills it) until its parent calls wait and gets it's final status. This means that even if init does nothing but call init over and over there could be a small amount of time where a process may show up as a zombie. If processes show up as children of init (0=ppid) for long amounts of time (seconds) then something is probably wrong.
-- can any one write some C code to make a zombie it's parent is Init?
This isn't clear, but I think you want:
pid_t f = fork();
if (f > 0) {
    exit(0); // this is the parent dying, so the child will be an orphan
             // and get adopted by init
} else if (f == 0) {
    sleep(100); // This is the child doing something that takes enough time for
                // its parent to commit suicide (exit(0)) and then for you to
                // observe that it has now been adopted by init
    exit(0);    // And now it dyes as well, so init should reap its status, but
                // it may be a zombie for a short amount of time first.
} else /* error condition would be handled here */
-- can zombies refusing to release some lock on memory??
Zombies can't hold onto much of anything. They lose all of their memory pages, open file handles, ...etc. Pretty much everything the operating system can figure out how to free up should get freed. It would be a bug not to, but remember that the OS has to know that it is something that is supposed to be freed. It is very easy to create resources in user space that should be freed when a program dies that the OS doesn't know are supposed to be freed.


#include   <sys/types.h>
#include   <sys/wait.h>
#include   "ourhdr.h"

int
main(void)
{
   pid_t   pid;

   if ( (pid = fork()) < 0)
       err_sys("fork error");
   else if (pid == 0) {       /* first child */
       if ( (pid = fork()) < 0)
           err_sys("fork error");
       else if (pid > 0)
           exit(0);   /* parent from second fork == first child */

       /* We're the second child; our parent becomes init as soon
           as our real parent calls exit() in the statement above.
           Here's where we'd continue executing, knowing that when
           we're done, init will reap our status. */

       sleep(2);
       printf("second child, parent pid = %d ", getppid());
       exit(0);
   }

   if (waitpid(pid, NULL, 0) != pid)   /* wait for first child */
       err_sys("waitpid error");

   /* We're the parent (the original process); we continue executing,
       knowing that we're not the parent of the second child. */

   exit(0);
}

Zombie.c:
#include   "ourhdr.h"

int
main(void)
{
   pid_t   pid;

   if ( (pid = fork()) < 0)
       err_sys("fork error");
   else if (pid == 0)       /* child */
       exit(0);

   /* parent */
   sleep(4);

   system("ps");

   exit(0);
}


Vfork3:
#include   <sys/types.h>
#include   "ourhdr.h"

static void   f1(void), f2(void);

int
main(void)
{
   f1();
   f2();
   _exit(0);
}

static void
f1(void)
{
   pid_t   pid;

   if ( (pid = vfork()) < 0)
       err_sys("vfork error");
   /* child and parent both return */
}

static void
f2(void)
{
   char   buf[1000];       /* automatic variables */
   int       i;

   for (i = 0; i < sizeof(buf); i++)
       buf[i] = 0;
}


Wait1.c:
#include   <sys/types.h>
#include   <sys/wait.h>
#include   "ourhdr.h"

int
main(void)
{
   pid_t   pid;
   int       status;

   if ( (pid = fork()) < 0)
       err_sys("fork error");
   else if (pid == 0)       /* child */
       exit(7);

   if (wait(&status) != pid)       /* wait for child */
       err_sys("wait error");
   pr_exit(status);               /* and print its status */

   if ( (pid = fork()) < 0)
       err_sys("fork error");
   else if (pid == 0)       /* child */
       abort();           /* generates SIGABRT */

   if (wait(&status) != pid)       /* wait for child */
       err_sys("wait error");
   pr_exit(status);               /* and print its status */

   if ( (pid = fork()) < 0)
       err_sys("fork error");
   else if (pid == 0)       /* child */
       status /= 0;       /* divide by 0 generates SIGFPE */

   if (wait(&status) != pid)       /* wait for child */
       err_sys("wait error");
   pr_exit(status);               /* and print its status */

   exit(0);
}