Weiter | Weiter | Weiter | Weiter | Kommentar

all-inOne, section 5.

5.  Processes

Silberschatz:   page 87   page 114
A process is an execution stream in the context of a particular process state.


--
Registers
--
Stack
--
Memory (global variables and dynamically allocated memory)
--
Open file tables
--
Signal management information

Key concept: Processes are separated; no process can directly affect the state of another process.


--
Your command shell is a process.
--
When you execute a program you have just compiled, the OS generates a process to run the compiler.
--
Your WWW browser is a process.

5.1.  System View of a Process

We are looking for the answers!

Question: Which kind of OS ((single|multi) process) would you develop for a HP SureStore E Disk Array XP512.

5.2.  The Process Model

A process is a an executing program, including the

5.3.  Process Hierarchie

An operating system that supports the process concept must provide one way to create all the processes needed.

In UNIX processes are created by the fork() system call, which creates an identical copy of the calling process.

After the fork()-call the parent continues to run in parallel with the child. The child can also call fork() and so on ...

A process can overlays a new process image on its process with a exec systemcall. File descriptors open in the calling process remain open in the new process, except for those whose close-on-exec flag is set; (see fcntl(2)). For those file descriptors that remain open, the file pointer is unchanged. Signals that are being caught by the calling process are set to the default disposition in the new process image (see signal(3C)). Otherwise, the new process image inherits the signal dispositions of the calling process.

A process can be killed with kill() from another process, or a process may kill itself with exit() or _exit().

We have the following situation under UNIX:

1.   Parent <-> child hierarchie -> process tree
2.   Time invariable (invariant)
3.   process groups

Question: Where does the first process come from? Question: How does popen(...) works?

 1      FILE * popen(const char *cmdstring, const char *type)
 2      {
 3        ...
 4        if ( pipe(pfd) ) < 0 )
 5          return(NULL);       
 6      
 7        if ( (pid = fork()) < 0)
 8          return(NULL);       
 9        else if (pid == 0) {          /* child */
10          if (*type == 'r') {
11            close(pfd[0]);
12            dup(pfd[1], 1);
13            ...
14          } else {
15            ...
16          }
17          execl(SHELL, "sh", "-c", cmdstring, (char *) 0);
18          _exit(127);
19        }
20        if (*type == 'r') {           /* parent */
21          close(pfd[1]);
22          if ( (fp = fdopen(pfd[0], type)) == NULL)
23            return(NULL);
24        } else {
25          ...
26        }
27        return(fp);
28      }

Source Code: Src/5/popen.c

5.4.  A Pictural Description for fork/exec Sequence

Fork:

Fork/Exec:

Please explain the following program:

 1      #include <stdio.h>
 2      #include <signal.h>
 3      #include <sys/wait.h>
 4      
 5      void catch(int sig)
 6      {
 7        signal(sig, SIG_IGN);
 8        printf("%d: Got signal %d\n", getpid(), sig);
 9      }
10      
11      int main(int argc, char ** argv)
12      {       FILE * fp;
13        char buffer[1024];
14        signal( 8 , catch );
15        signal( 9 , catch );
16        signal( 10 , catch );
17        if ( ( fp = fopen("signal_fork.c", "r" ) ) == -1 )
18          exit(1);
19        fscanf(fp, "%s", buffer); printf("buffer = %s\n", buffer );
20      
21        switch ( fork() )     {
22          case -1:    perror("fork failed");
23              exit(1);
24          case  0:    fscanf(fp, "%s", buffer);
25              printf("Son: buffer = %s\n", buffer );
26              break;
27          default:    fscanf(fp, "%s", buffer);
28              printf("Parent: buffer = %s\n", buffer );
29        }
30        exit(0);
31      }

Source Code: Src/5/signal_fork.c

Please explain the following program:

 1      #include <stdio.h>
 2      #include <signal.h>
 3      #include <sys/wait.h>
 4      
 5      void catch(int sig)
 6      {
 7        signal(sig, SIG_IGN);
 8        printf("%d: Got signal %d\n", getpid(), sig);
 9      }
10      
11      int main(int argc, char ** argv)
12      {       signal( 8 , catch );
13        signal( 9 , catch );
14        signal( 10 , catch );
15      
16        switch ( fork() )     {
17          case -1:    perror("fork failed");
18              exit(1);
19          case  0:    
20              printf("Son: exec ...\n");
21              execl("/bin/sh", "sh", "-c",
22                "/usr/bin/sleep 1234", (char *) 0);
23          default:    printf("Parent: .... \n");
24              sleep(12345);
25        }
26        exit(0);
27      }

Source Code: Src/5/signal_exec.c

5.5.  Process States

Each process is an indepedent entity, with its own program counter and internal state. Let's take a look to the following commands:

% cd  /usr/share/lib/dict/
% ls -l words
-r--r--r--   1 bin      bin       206662 May  2  1996 words
% cat words | grep 'whale' | tr 'a-z' 'A-Z'
WHALE

Depending on the relative speed of the two processes, it may happen that grep is ready to run, but there is no input for it. It must then block until some input is available.

When a process is using the CPU, it is actually running and doing some work. However, it will not always stay in that state.

If a process does I/O and the device is not ready or just slow, the process will become blocked and be unable to do any more work until the I/O is complete.

In a multitasking environment, a process is not allowed to use the CPU all the time. At intervals (maybe signalled by a timer interrupt) it will be stopped by the OS so that another process can run. In this state it is not running, but it is runnable.

A process is in one of the following states:

1.   running
2.   ready/runnable
3.   blocked

The process states and transitions are

[picture]

1.   process blocks for input
2.   scheduler picks another process
3.   scheduler picks this process
4.   input is available

Here are some reasons for possible transition:

Fundamental Scheduling Law: A process cannot run if there is a ready process of higher priority. We will see this later.

5.6.  Process Control Block


--
Process State: ready, running waitung
--
Program counter: indicates the next instruction to be executed
--
CPU registers: see compiler design
--
CPU scheduling information: priority, scheduling parameters,
--
Memory managemet information: page tables, segment table
--
Accounting: amount of used CPU time, process number
--
I/O status information: open files etc.

5.7.  Process Scheduling

Silberschatz:   page 135   page 171


--
The objective of timesharing is to have the CPU switch between processes so frequently that users can interact with each program as it is running
--
This switch involvess:

--
Switching context
--
Switching to user mode
--
Jump to the proper location and continue the program.

--
Bottom line is that the OS plays a shell game and needs to switch from process to process
--
Scheduling refers to the algorithms used to implement the switching Process Scheduling.
Criterias for a good scheduling algorithm:

1.   Fairness: make sure each gets its fair share of CPU.
2.   Efficency: keep the CPU busy 100% of the time.
3.   Response time: minimize response time for interactive users.
4.   Turnaround: minimize the time batch users must wait for the output.
5.   Throughput: maximize the number of processes per hour.

Possible ideas:

Think about: it takes time to pick another process!

5.8.  Context Switch

5.9.  Scheduler Overview

5.10.  Nonpreemptive: First Come first Serve


--
Easy to implement
--
Ignores Service Time
--
Not a great perfomer.

5.11.  Nonpreemptive: Shortest Job Next

i   T(p of i)
--------------
0   350
1   150
2   100
3   200
4   900

Please draw the Gantt charts!

5.12.  Premptive: Round Robin Scheduling

Each process will be assigned a time interval, quantum, which it is allowed to run or until it blocks.

ADD a few more things here ....

Round robind scheduling makes the implicit assumption that all processes are equally important.

Is this a good or bad assumption?

How long will it take 3 processes, each needs 3 time slices, to complete? Let's say the context switch takes 1 time slice.

+------+-----+---------------+------+
|Slice | Job | consumed time | done |
+------+-----+---------------+------+
|1:    |     |               |      |
+------+-----+---------------+------+
|2:    |     |               |      |
+------+-----+---------------+------+
|4:    |     |               |      |
+------+-----+---------------+------+
|4:    |     |               |      |
+------+-----+---------------+------+
|5:    |     |               |      |
+------+-----+---------------+------+
|6:    |     |               |      |
+------+-----+---------------+------+
|7:    |     |               |      |
+------+-----+---------------+------+
|8:    |     |               |      |
+------+-----+---------------+------+
|9:    |     |               |      |
+------+-----+---------------+------+
|10:   |     |               |      |
+------+-----+---------------+------+
|11:   |     |               |      |
+------+-----+---------------+------+
|12:   |     |               |      |
+------+-----+---------------+------+
|13:   |     |               |      |
+------+-----+---------------+------+
|14:   |     |               |      |
+------+-----+---------------+------+
|15:   |     |               |      |
+------+-----+---------------+------+
|16:   |     |               |      |
+------+-----+---------------+------+
|17:   |     |               |      |
+------+-----+---------------+------+
|18:   |     |               |      |
+------+-----+---------------+------+
|19:   |     |               |      |
+------+-----+---------------+------+

5.13.  Priority Scheduling

The basic idea is straightforward: each process is assigned a priority, and the process with the highest priority is allowed to run.

Priorities can be assigned by a process

--
statically or
--
dynamically.

Statically:

--
money
--
...

Dynamically:

--
I/O bound versus CPU bound
--
consumed CPU time
--
consumed other resources
--
...

A simple algorithm for giving a good service to an I/O bound process is to set the priority to

[equation]

where f is the fraction of the last quantum of time that a process used.

How long will it take 3 processes, each need 3 time slices, to complete? Process 1 uses only 25% of each time slice, it needs 1 time slice. Process 2 uses only 50% of each time slice, it needs 2 time slice. Process 3 uses only 100% of each time slice, it needs 3 time slices. The initial priority for each process is 1. Use round robin if two or more processes have the same priority. Let's say the context switch takes 1 time slice.

+------+-----+----------+---------------+------+
|slice | job | priority | consumed time | done |
+------+-----+----------+---------------+------+
|1:    |     |          |               |      |
+------+-----+----------+---------------+------+
|2:    |     |          |               |      |
+------+-----+----------+---------------+------+
|4:    |     |          |               |      |
+------+-----+----------+---------------+------+
|4:    |     |          |               |      |
+------+-----+----------+---------------+------+
|5:    |     |          |               |      |
+------+-----+----------+---------------+------+
|6:    |     |          |               |      |
+------+-----+----------+---------------+------+
|7:    |     |          |               |      |
+------+-----+----------+---------------+------+
|8:    |     |          |               |      |
+------+-----+----------+---------------+------+
|9:    |     |          |               |      |
+------+-----+----------+---------------+------+
|10:   |     |          |               |      |
+------+-----+----------+---------------+------+
|11:   |     |          |               |      |
+------+-----+----------+---------------+------+
|12:   |     |          |               |      |
+------+-----+----------+---------------+------+
|13:   |     |          |               |      |
+------+-----+----------+---------------+------+
|14:   |     |          |               |      |
+------+-----+----------+---------------+------+
|15:   |     |          |               |      |
+------+-----+----------+---------------+------+
|16:   |     |          |               |      |
+------+-----+----------+---------------+------+
|17:   |     |          |               |      |
+------+-----+----------+---------------+------+
|18:   |     |          |               |      |
+------+-----+----------+---------------+------+
|19:   |     |          |               |      |
+------+-----+----------+---------------+------+

Lets do the same with this algorithm:

[equation]

where f is the fraction of the last quatum of time that a process used.

How long will it take 3 processes, each need 3 time slices, to complete?

Priorities must be adjusted from time to time.

5.14.  Multiple Queues

Use priorities to disfavor long running processes. One example of adaptive scheduler schemes:

Multi-Level Feedback Queues (or Exponential Queue)

--
Run all jobs in highest priority queue. If empty, go to next queue.
--
Give new process high priority and shorten time slice (1 unit).
--
If process uses entire time slice without blocking, decrease priority by 1 and double time slice for next time.

--
time slice is always <= MAXIMUM
--
priority is always >= 1
--
If process blocks before time slice has elapsed, then increase priority and decrease time slice.

--
time slice is always >= minimum time slice
--
priority is always <= MAXIMUM Priority

CTSS (MIT, early 1960's) was the first to use exponential queues.

5.15.  Execution of Processes in Class

Example 1


--
Round Robin Scheduling on a level
--
The scheduler executes only one instruction then pics an other process.
--
every process is loaded, pc == 1 for all processes.
--
The output is: pid: instruction, if instruction [isin] { a - z }

[picture]

Example 2

Note: added to the notes: Mon Dec 18 14:17:40 EST 2000


--
Round Robin Scheduling on a level
--
The scheduler executes only one instruction then pics an other process.
--
every process is loaded, pc == 1 for all processes.
--
The output is: pid: instruction, if instruction [isin] { a - z }

[picture]

Example 3

Note: added to the notes: Mon Dec 18 14:17:40 EST 2000


--
Round Robin Scheduling on a level
--
The scheduler executes only one instruction then pics an other process.
--
every process is loaded, pc == 1 for all processes.
--
The output is: pid: instruction, if instruction [isin] { a - z }

[picture]

5.16.  Implemetation of Processes

The OS maintains a table (an array of structures), called the process table, with one entry per process.

Why is the data structure for the process table an array?

What is a possible data structure for a process?

Entries in this table are often called process control blocks and must contain the information needed so that the process can be loaded into memory and run. This includes

--   process state
--   memory state
--   resource state
--   the value of each register
--   the program counter
--   the stack pointer

for each process.

Information about the state that the process is (running, runnable, blocked) and is need to restore the process.

In addition it may contain extra fields such as:

--   process ID of itself, its parent, etc.
--   elapsed time.
--   pending signals that have not yet been dealt with
     (eg signal arrived while the process was asleep).

5.17.  Memory state

Pointers to the various memory areas used by the program need to be kept, so that they can be relocated back as needed.

5.18.  Resource state

The process will generally have files open, be in particular directory, have a certain user ID, etc. The information about these will need to be stored also.

For example, in Unix each process has a file table. The first entry in this (file descriptor zero) is for the processes' standard input, the second entry is for standard output, the third for standard error. Additional entries are made when the process opens more files.

Let's take a look what happens with the process table, if we let the following run:

% example 1
% ps
   PID TTY      TIME CMD
 24245 pts/10   0:01 bash
% date
Wed Sep  3 15:41:21 EDT 1997
% echo $?
0
% example 2
% ps
   PID TTY      TIME CMD
 24245 pts/10   0:01 bash
% date &
[1] 26208
% Wed Sep  3 15:47:10 EDT 1997

[1]+  Done                    date
% echo $?

Problems:

1.   How does the process table now look?
2.   What happend, if a signal is sent to blocked process?
3.   What happens if a new signal arrived,
     when the process is in a signal handling procedure?
4.   How many signals can be sent to a blocked process?
5.   Is it possible to use signals for process communication?
6.   Is it possible to use signals for a stable process communication?

5.19.  Processes and UNIX

Here are some notes about a Unix process [version xyz???]. The reference for this is the Stevens book (Advanced Programming in the Unix Environment). Maybe you would like to read Tannenbaum chapter 7.

The following figure (from Stevens page 168) describes the layout of the address space (virtual) of a process. This space is essentially divided in two parts, a top part with the stack, and a bottom part with the heap etc. Between the two is empty space. The stack area is usually terminated by a guard, i.e. an area to which the program does not have access rights, so that an exception will be raised when running out of stack.

5.20.  Threads


--
Ressource sharing
--
Economy


--
provided by a library (POSIX: PThreads, Mach: C-threads, Solaris: threads)
--
fast to create and manage
--
drawbacks: if the kernel is single threaded


--
supported by the OS
--
generally slower as User Threads
--
multiprocesser environment: can be scheduled on different processes
--
Windows NT, Solaris, are os's that support kernel threads.


--
Many-to-One (One kernel thread [larr] many user threads)
--
One-to-One (One kernel thread [larr] one user threads)
--
Many-to-Many (many kernel thread [larr] many user threads)


--
suspend();
--
sleep();
--
synchronization

5.21.  Processes and UNIX and a Shell

 1      % ps -edf | grep bischof | sed 6q
 2           UID   PID  PPID  C    STIME TTY      TIME CMD
 3       bischof   332     1  0   Sep 01 console  0:01 /opt/gnu/bin/bash
 4       bischof  8661  8658  0 15:54:26 pts/4    0:02 bash
 5       bischof   850   849  0   Sep 01 ?        0:01 (dns helper)
 6       bischof  8563  4442  0 15:46:29 pts/5    0:00 vi c.04
 7       bischof   342   332  0   Sep 01 console  0:00 /bin/sh
 8      %
 9      % # processes bound on this terminal
10      % tty
11      /dev/pts/4
12      % ps
13         PID TTY      TIME CMD
14        8661 pts/4    0:02 bash
15        8658 pts/4    0:00 vi
16        8568 pts/4    0:01 bash
17      %
18      % # create a new process
19      % sleep 1000 &
20      [1] 8875
21      % ps -l | egrep '(sleep|UID)'
22       F S   UID   PID  PPID  C PRI NI     ADDR     SZ    WCHAN TTY      TIME CMD
23       8 S 22008  8875  8661  0  71 20 f6086320    182 f60864f0 pts/4    0:00 sleep
24      %
25      % # kill a process
26      % kill 8875
27      % ps
28         PID TTY      TIME CMD
29        8661 pts/4    0:03 bash
30        8658 pts/4    0:00 vi
31        8568 pts/4    0:01 bash
32      [1]+  Terminated              sleep 1000
33      %
34      %  # stop a process
35      % sleep 1000
36      ^Z
37      [1]+  Stopped                 sleep 1000
38      % # wake up!
39      % fg
40      sleep 1000
41      ^C
42      % # take a look at
43      # http://www.cs.oswego.edu/~bischof/Man/ \
44      # _Man_Solaris_2.5_html/html5/signal.5.html
45      %
46      % # process synchronization via pipes
47      %
48      % niscat passwd.org_dir | sed 's/Bischof/HP/' | grep HP
49      bischof:z03l03sqb2OD.:22008:7000:Hans-Peter HP:...
50      % niscat passwd.org_dir | grep HP
51      % niscat passwd.org_dir | grep bischof
52      bischof:z03l03sqb2OD.:22008:7000:Hans-Peter Bischof:...
53      %
54      
55      % # process synchronization via fifos
56      %
57      % mkfifo myFifo
58      % ls -l myFifo
59      prw-r--r--   1 bischof  cs             0 Sep  2 17:00 myFifo
60      % echo 'I like it' > myFifo &
61      9390
62      % cat myFifo
63      I like it

Source Code: Src/5/unix_process

5.22.  Processes and UNIX and a C-Program

Get some information (getpid(), (getppid(), (getuid(), (geteuid():

5.23.  Signals

Signals are software interrupts and can be generated with a variety of causes (divide by 0, send via signal(), control C etc). The signal causes the process temporarily to suspend whatever it was doing, save its registers on the stack and start running a special signal handling procedure. When the signal handler is done, the running process is restarted in the state it was just before.

An example:

Write the signal number of each arrived signal.

 1      /*
 2       *      Module:         4_signal.c
 3       *      Description:    print the name of each arrived signal.
 4       */
 5      #include <stdio.h>
 6      #include <signal.h>
 7      #include <sys/wait.h>
 8      
 9      /*
10       * The signal handling function.
11       */
12      void catch(int sig)
13      {
14        signal(sig, SIG_IGN);
15        printf("%d: Got signal %d\n", getpid(), sig);
16      }
17      
18      int main(int argc, char ** argv)
19      {       int i;
20        for ( i = SIGHUP; i < SIGCANCEL; i++ )
21          signal( i , catch );
22      
23        while ( 1 ) ;
24        exit(0);
25      }

Source Code: Src/5/signal.c

Compilation and a test run:

% gcc -o 5/signal 5/signal.c
% 5/signal
^C3577: Got signal 2
^C^C^C^C^C^C^C
^Z3577: Got signal 24
^Z^Z^Z^Z^Z^Z^Z^Z

Try kill -9 from an other window:

% ps -edf | grep 5/signal
 bischof  3584  1629  1 12:09:22 pts/2    0:00 grep 5/signal
 bischof  3577  3058 92 12:07:21 pts/6    1:52 5/signal
% kill -9 3577

5.24.  Lifecyle of a Process

The following figure derived from Stevens shows how exit() and _exit() are related.

5.25.  A possible implementation of a Processtable

Let's take a look into the Linux 2.7 kernel source code.

5.26.  Process table structure:

Linux/include/linux/sched.h

 1      struct task_struct {
 2      /* these are hardcoded - don't touch */
 3        volatile long state;  /* -1 unrunnable, 0 runnable, >0 stopped */
 4        long counter;
 5        long priority;
 6        unsigned long signal;
 7        unsigned long blocked;        /* bitmap of masked signals */
 8        unsigned long flags;  /* per process flags, defined below */
 9        int errno;
10        long debugreg[8];  /* Hardware debugging registers */
11        struct exec_domain *exec_domain;
12      /* various fields */
13        struct linux_binfmt *binfmt;
14        struct task_struct *next_task, *prev_task;
15        struct task_struct *next_run,  *prev_run;
16        unsigned long saved_kernel_stack;
17        unsigned long kernel_stack_page;
18        int exit_code, exit_signal;
19        /* ??? */
20        unsigned long personality;
21        int dumpable:1;
22        int did_exec:1;
23        /* shouldn't this be pid_t? */
24        int pid;
25        int pgrp;
26        int tty_old_pgrp;
27        int session;
28        /* boolean value for session group leader */
29        int leader;
30        int   groups[NGROUPS];
31        /*
32         * pointers to (original) parent process, youngest child, younger sibling,
33         * older sibling, respectively.  (p->father can be replaced with
34         * p->p_pptr->pid)
35         */
36        struct task_struct *p_opptr, *p_pptr, *p_cptr, *p_ysptr, *p_osptr;
37        struct wait_queue *wait_chldexit;     /* for wait4() */
38        unsigned short uid,euid,suid,fsuid;
39        unsigned short gid,egid,sgid,fsgid;
40        unsigned long timeout, policy, rt_priority;
41        unsigned long it_real_value, it_prof_value, it_virt_value;
42        unsigned long it_real_incr, it_prof_incr, it_virt_incr;
43        struct timer_list real_timer;
44        long utime, stime, cutime, cstime, start_time;
45      /* mm fault and swap info: this can arguably be seen as either mm-specific or thread-specific */
46        unsigned long min_flt, maj_flt, nswap, cmin_flt, cmaj_flt, cnswap;
47        int swappable:1;
48        unsigned long swap_address;
49        unsigned long old_maj_flt;    /* old value of maj_flt */
50        unsigned long dec_flt;                /* page fault count of the last time */
51        unsigned long swap_cnt;               /* number of pages to swap on next pass */
52      /* limits */
53        struct rlimit rlim[RLIM_NLIMITS];
54        unsigned short used_math;
55        char comm[16];
56      /* file system info */
57        int link_count;
58        struct tty_struct *tty; /* NULL if no tty */
59      /* ipc stuff */
60        struct sem_undo *semundo;
61        struct sem_queue *semsleeping;
62      /* ldt for this task - used by Wine.  If NULL, default_ldt is used */
63        struct desc_struct *ldt;
64      /* tss for this task */
65        struct thread_struct tss;
66      /* filesystem information */
67        struct fs_struct *fs;
68      /* open file information */
69        struct files_struct *files;
70      /* memory management info */
71        struct mm_struct *mm;
72      /* signal handlers */
73        struct signal_struct *sig;
74      #ifdef __SMP__
75        int processor;
76        int last_processor;
77        int lock_depth;               /* Lock depth. We can context switch in and out of holding a syscall kernel lock... */  
78      #endif  
79      };

Source Code: Src/5/task_struct

5.27.  Declaration of the Process table:

Linux/kernel/sched.c

struct task_struct * task[NR_TASKS] = {&init_task, };

5.28.  Creation of a Process

Linux/kernel/fork.c

 1      /*
 2       *  Ok, this is the main fork-routine. It copies the system process
 3       * information (task[nr]) and sets up the necessary registers. It
 4       * also copies the data segment in its entirety.
 5       */
 6      int do_fork(unsigned long clone_flags, unsigned long usp, struct pt_regs *regs)
 7      {
 8        int nr;
 9        int error = -ENOMEM;
10        unsigned long new_stack;
11        struct task_struct *p;
12      
13        p = (struct task_struct *) kmalloc(sizeof(*p), GFP_KERNEL);
14        if (!p)
15          goto bad_fork;
16        new_stack = alloc_kernel_stack();
17        if (!new_stack)
18          goto bad_fork_free_p;
19        error = -EAGAIN;
20        nr = find_empty_process();
21        if (nr < 0)
22          goto bad_fork_free_stack;
23      
24        *p = *current;
25      
26        if (p->exec_domain && p->exec_domain->use_count)
27          (*p->exec_domain->use_count)++;
28        if (p->binfmt && p->binfmt->use_count)
29          (*p->binfmt->use_count)++;
30      
31        p->did_exec = 0;
32        p->swappable = 0;
33        p->kernel_stack_page = new_stack;
34        *(unsigned long *) p->kernel_stack_page = STACK_MAGIC;
35        p->state = TASK_UNINTERRUPTIBLE;
36        p->flags &= ~(PF_PTRACED|PF_TRACESYS|PF_SUPERPRIV);
37        p->flags |= PF_FORKNOEXEC;
38        p->pid = get_pid(clone_flags);
39        p->next_run = NULL;
40        p->prev_run = NULL;
41        p->p_pptr = p->p_opptr = current;
42        p->p_cptr = NULL;
43        init_waitqueue(&p->wait_chldexit);
44        p->signal = 0;
45        p->it_real_value = p->it_virt_value = p->it_prof_value = 0;
46        p->it_real_incr = p->it_virt_incr = p->it_prof_incr = 0;
47        init_timer(&p->real_timer);
48        p->real_timer.data = (unsigned long) p;
49        p->leader = 0;                /* session leadership doesn't inherit */
50        p->tty_old_pgrp = 0;
51        p->utime = p->stime = 0;
52        p->cutime = p->cstime = 0;
53      #ifdef __SMP__
54        p->processor = NO_PROC_ID;
55        p->lock_depth = 1;
56      #endif
57        p->start_time = jiffies;
58        task[nr] = p;
59        SET_LINKS(p);
60        nr_tasks++;
61      
62        error = -ENOMEM;
63        /* copy all the process information */
64        if (copy_files(clone_flags, p))
65          goto bad_fork_cleanup;
66        if (copy_fs(clone_flags, p))
67          goto bad_fork_cleanup_files;
68        if (copy_sighand(clone_flags, p))
69          goto bad_fork_cleanup_fs;
70        if (copy_mm(clone_flags, p))
71          goto bad_fork_cleanup_sighand;
72        copy_thread(nr, clone_flags, usp, p, regs);
73        p->semundo = NULL;
74      
75        /* ok, now we should be set up.. */
76        p->swappable = 1;
77        p->exit_signal = clone_flags & CSIGNAL;
78        p->counter = current->counter >> 1;
79        wake_up_process(p);                   /* do this last, just in case */
80        ++total_forks;
81        return p->pid;
82      
83      bad_fork_cleanup_sighand:
84        exit_sighand(p);
85      bad_fork_cleanup_fs:
86        exit_fs(p);
87      bad_fork_cleanup_files:
88        exit_files(p);
89      bad_fork_cleanup:
90        if (p->exec_domain && p->exec_domain->use_count)
91          (*p->exec_domain->use_count)--;
92        if (p->binfmt && p->binfmt->use_count)
93          (*p->binfmt->use_count)--;
94        task[nr] = NULL;
95        REMOVE_LINKS(p);
96        nr_tasks--;
97      bad_fork_free_stack:
98        free_kernel_stack(new_stack);
99      bad_fork_free_p:
100       kfree(p);
101     bad_fork:
102       return error;
103     }

Source Code: Src/5/do_fork

5.29.  Question


--
initial time slice 1
--
p1:
0.5
0.5
0.5
1
p1:
2
0.25
0.5


Weiter | Weiter | Weiter | Weiter | Kommentar


Created by unroff, java2html && hp-tools. © by Hans-Peter Bischof. All Rights Reserved (2001).
It is not allowed to print these pages on a CAST printer.
Last modified 14/February/2001