慶應義塾大学
2008年度 春学期

システム・ソフトウェア
System Software / Operating Systemsオペレーティングシステム

2008年度春学期 火曜日2時限
科目コード: 60730
開講場所:SFC
授業形態:講義
担当: Rodney Van Meter
E-mail: rdv@sfc.keio.ac.jp

第3回 4月22日 プロセスとスレッド
Lecture 3, April 22: Processプロセスes and Threads

Butler Lampson, from Microsoft

Class Discussion of Lampson

Last week, you were asked to read Lampson,
Hints for Computer System Design. What did you learn? (We will discuss some of the slogans in the figure from the paper.)

What's a Processプロセス?

Several times already this term I've used the term "processプロセス". So what is a processプロセス, anyway? A processプロセス is an instance of a running program on a multitasking or multiprogrammed OS. If we ignore performance, the concept of a processプロセス is what allows an application program to think that it has the entire computer to itself. (In systems with virtual memory仮そう記録, the processプロセス abstraction also allows programs to think they have lots of memory, whether or not they really do.)

Segments

A "segment" of a Unix processプロセス is one of its primary data areas: the text segment is the program itself (including shared libraries), the data segment is for most variables (of several types; those created using the malloc() memory acquisition routine, primarily), and the stack segment holds, well, the stack. The portion of the data segment that is dynamically allocated and deallocated is often called the memory heap.

Some operating systemsオペレーティングシステム explicitly support requests for memory already filled with zeroes or not; the choice of which to use is for efficiency. The choice the OS makes on whether or not to supply memory that is not zero-filled is both an efficiency and a security issue. In Unix systems, application programs cannot assume that freshly-allocated memory contains zeroes, but if it does not, it is usually because the memory allocator has reassigned memory that the same processプロセス has recently freed. Handing out memory that other processプロセスes have recently freed would allow one processプロセス to read some of another's memory, without permission許可!

Processプロセス control structures

From include/linux/sched.h:

struct task_struct {
	volatile long state;	/* -1 unrunnable, 0 runnable, >0 stopped */
	struct thread_info *thread_info;
	atomic_t usage;
	unsigned long flags;	/* per processプロセス flags, defined below */
	unsigned long ptrace;

	int lock_depth;		/* BKL lock depth */

#ifdef CONFIG_SMP
#ifdef __ARCH_WANT_UNLOCKED_CTXSW
	int oncpu;
#endif
#endif
	int load_weight;	/* for niceness load balancing purposes */
	int prio, static_prio, normal_prio;
	struct list_head run_list;
	struct prio_array *array;

	unsigned short ioprio;
#ifdef CONFIG_BLK_DEV_IO_TRACE
	unsigned int btrace_seq;
#endif
	unsigned long sleep_avg;
	unsigned long long timestamp, last_ran;
	unsigned long long sched_time; /* sched_clock time spent running */
	enum sleep_type sleep_type;

	unsigned long policy;
	cpumask_t cpus_allowed;
	unsigned int time_slice, first_time_slice;

#if defined(CONFIG_SCHEDSTATS) || defined(CONFIG_TASK_DELAY_ACCT)
	struct sched_info sched_info;
#endif

	struct list_head tasks;
	/*
	 * ptrace_list/ptrace_children forms the list of my children
	 * that were stolen by a ptracer.
	 */
	struct list_head ptrace_children;
	struct list_head ptrace_list;

	struct mm_struct *mm, *active_mm;

/* task state */
	struct linux_binfmt *binfmt;
	long exit_state;
	int exit_code, exit_signal;
	int pdeath_signal;  /*  The signal sent when the parent dies  */
	/* ??? */
	unsigned long personality;
	unsigned did_exec:1;
	pid_t pid;
	pid_t tgid;

#ifdef CONFIG_CC_STACKPROTECTOR
	/* Canary value for the -fstack-protector gcc feature */
	unsigned long stack_canary;
#endif
	/* 
	 * pointers to (original) parent processプロセス, youngest child, younger sibling,
	 * older sibling, respectively.  (p->father can be replaced with 
	 * p->parent->pid)
	 */
	struct task_struct *real_parent; /* real parent processプロセス (when being debugged) */
	struct task_struct *parent;	/* parent processプロセス */
	/*
	 * children/sibling forms the list of my children plus the
	 * tasks I'm ptracing.
	 */
	struct list_head children;	/* list of my children */
	struct list_head sibling;	/* linkage in my parent's children list */
	struct task_struct *group_leader;	/* threadgroup leader */

	/* PID/PID hash table linkage. */
	struct pid_link pids[PIDTYPE_MAX];
	struct list_head thread_group;

	struct completion *vfork_done;		/* for vfork() */
	int __user *set_child_tid;		/* CLONE_CHILD_SETTID */
	int __user *clear_child_tid;		/* CLONE_CHILD_CLEARTID */

	unsigned long rt_priority;
	cputime_t utime, stime;
	unsigned long nvcsw, nivcsw; /* context switch counts */
	struct timespec start_time;
/* mm fault and swap info: this can arguably be seen as either mm-specific or thread-specific */
	unsigned long min_flt, maj_flt;

  	cputime_t it_prof_expires, it_virt_expires;
	unsigned long long it_sched_expires;
	struct list_head cpu_timers[3];

/* processプロセス credentials */
	uid_t uid,euid,suid,fsuid;
	gid_t gid,egid,sgid,fsgid;
	struct group_info *group_info;
	kernelカーネル_cap_t   cap_effective, cap_inheritable, cap_permitted;
	unsigned keep_capabilities:1;
	struct user_struct *user;
#ifdef CONFIG_KEYS
	struct key *request_key_auth;	/* assumed request_key authority */
	struct key *thread_keyring;	/* keyring private to this thread */
	unsigned char jit_keyring;	/* default keyring to attach requested keys to */
#endif
	/*
	 * fpu_counter contains the number of consecutive context switches
	 * that the FPU is used. If this is over a threshold, the lazy fpu
	 * saving becomes unlazy to save the trap. This is an unsigned char
	 * so that after 256 times the counter wraps and the behavior turns
	 * lazy again; this to deal with bursty apps that only use FPU for
	 * a short time
	 */
	unsigned char fpu_counter;
	int oomkilladj; /* OOM kill score adjustment (bit shift). */
	char comm[TASK_COMM_LEN]; /* executable name excluding path
				     - access with [gs]et_task_comm (which lock
				       it with task_lock())
				     - initialized normally by flush_old_exec */
/* file system info */
	int link_count, total_link_count;
#ifdef CONFIG_SYSVIPC
/* ipc stuff */
	struct sysv_sem sysvsem;
#endif
/* CPU-specific state of this task */
	struct thread_struct thread;
/* filesystem information情報 */
	struct fs_struct *fs;
/* open file information情報 */
	struct files_struct *files;
/* namespaces */
	struct nsproxy *nsproxy;
/* signal handlers */
	struct signal_struct *signal;
	struct sighand_struct *sighand;

	sigset_t blocked, real_blocked;
	sigset_t saved_sigmask;		/* To be restored with TIF_RESTORE_SIGMASK */
	struct sigpending pending;

	unsigned long sas_ss_sp;
	size_t sas_ss_size;
	int (*notifier)(void *priv);
	void *notifier_data;
	sigset_t *notifier_mask;
	
	void *security;
	struct audit_context *audit_context;
	seccomp_t seccomp;

/* Thread group tracking */
   	u32 parent_exec_id;
   	u32 self_exec_id;
/* Protection of (de-)allocation: mm, files, fs, tty, keyrings */
	spinlock_t alloc_lock;

	/* Protection of the PI data structures: */
	spinlock_t pi_lock;

#ifdef CONFIG_RT_MUTEXES
	/* PI waiters blocked on a rt_mutex held by this task */
	struct plist_head pi_waiters;
	/* Deadlock detection and priority inheritance handling */
	struct rt_mutex_waiter *pi_blocked_on;
#endif

#ifdef CONFIG_DEBUG_MUTEXES
	/* mutex deadlock detection */
	struct mutex_waiter *blocked_on;
#endif
#ifdef CONFIG_TRACE_IRQFLAGS
	unsigned int irq_events;
	int hardirqs_enabled;
	unsigned long hardirq_enable_ip;
	unsigned int hardirq_enable_event;
	unsigned long hardirq_disable_ip;
	unsigned int hardirq_disable_event;
	int softirqs_enabled;
	unsigned long softirq_disable_ip;
	unsigned int softirq_disable_event;
	unsigned long softirq_enable_ip;
	unsigned int softirq_enable_event;
	int hardirq_context;
	int softirq_context;
#endif
#ifdef CONFIG_LOCKDEP
# define MAX_LOCK_DEPTH 30UL
	u64 curr_chain_key;
	int lockdep_depth;
	struct held_lock held_locks[MAX_LOCK_DEPTH];
	unsigned int lockdep_recursion;
#endif

/* journalling filesystem info */
	void *journal_info;

/* VM state */
	struct reclaim_state *reclaim_state;

	struct backing_dev_info *backing_dev_info;

	struct io_context *io_context;

	unsigned long ptrace_message;
	siginfo_t *last_siginfo; /* For ptrace use.  */
/*
 * current io wait handle: wait queue entry to use for io waits
 * If this thread is processプロセスing aio, this points at the waitqueue
 * inside the currently handled kiocb. It may be NULL (i.e. default
 * to a stack based synchronous wait) if its doing sync IO.
 */
	wait_queue_t *io_wait;
/* i/o counters(bytes read/written, #syscalls */
	u64 rchar, wchar, syscr, syscw;
#if defined(CONFIG_TASK_XACCT)
	u64 acct_rss_mem1;	/* accumulated rss usage */
	u64 acct_vm_mem1;	/* accumulated virtual memory仮そう記録 usage */
	cputime_t acct_stimexpd;/* stime since last update */
#endif
#ifdef CONFIG_NUMA
  	struct mempolicy *mempolicy;
	short il_next;
#endif
#ifdef CONFIG_CPUSETS
	struct cpuset *cpuset;
	nodemask_t mems_allowed;
	int cpuset_mems_generation;
	int cpuset_mem_spread_rotor;
#endif
	struct robust_list_head __user *robust_list;
#ifdef CONFIG_COMPAT
	struct compat_robust_list_head __user *compat_robust_list;
#endif
	struct list_head pi_state_list;
	struct futex_pi_state *pi_state_cache;

	atomic_t fs_excl;	/* holding fs exclusive resources */
	struct rcu_head rcu;

	/*
	 * cache last used pipe for splice
	 */
	struct pipe_inode_info *splice_pipe;
#ifdef	CONFIG_TASK_DELAY_ACCT
	struct task_delay_info *delays;
#endif
};

Unix fork()

fork() is the only way in Unix to make a new processプロセス. The system callシステムコール copies the existing processプロセス and creates a child processプロセス. The child processプロセス inherits everything, including open file descriptors. In early versions of Unix, fork had to literally copy every page of data memory, but the program (or text segment) could be shared, because it is generally protected from being written to using processプロセスor page protection bits. However, copying all of the data memory can be expensive. Therefore, the vfork() system callシステムコール was later introduced; we won't go into details, but vfork() stops the parent from executing until the child is done with the memory. (The child should not actually touch the memory, however.) Modern systems generally implement fork() by copying only the page table of the calling processプロセス, and setting the data pages to copy on write. We will discuss copy on write when we cover memory management管理.

fork() is used very frequently. Every time the user requests execution of a program (via the shell), fork() is called. The child processプロセス then generally calls exec(), which replaces the currently running program (generally the shell) in this (the child) processプロセス, loading another program from disk, if necessary, and starting it. The parent can later choose to wait for the child processプロセス to finish, or the parent can continue executing its own work.

Most of the work in Linux is actually done in the copy_processプロセス function機能・関数. do_fork() is fairly short. copy_processプロセス makes new copies of certain structures, and creates new pointers to reference-counted objects for things that need to be shared.

From kernelカーネル/fork.c:

/*
 *  Ok, this is the main fork-routine.
 *
 * It copies the processプロセス, and if successful kick-starts
 * it and waits for it to finish using the VM if required.
 */
long do_fork(unsigned long clone_flags,
	      unsigned long stack_start,
	      struct pt_regs *regs,
	      unsigned long stack_size,
	      int __user *parent_tidptr,
	      int __user *child_tidptr)
{
	struct task_struct *p;
	int trace = 0;
	struct pid *pid = alloc_pid();
	long nr;

	if (!pid)
		return -EAGAIN;
	nr = pid->nr;
	if (unlikely(current->ptrace)) {
		trace = fork_traceflag (clone_flags);
		if (trace)
			clone_flags |= CLONE_PTRACE;
	}

	p = copy_processプロセス(clone_flags, stack_start, regs, stack_size, parent_tidptr, child_tidptr, nr);
	/*
	 * Do this prior waking up the new thread - the thread pointer
	 * might get invalid after that point, if the thread exits quickly.
	 */
	if (!IS_ERR(p)) {
		struct completion vfork;

		if (clone_flags & CLONE_VFORK) {
			p->vfork_done = &vfork;
			init_completion(&vfork);
		}

		if ((p->ptrace & PT_PTRACED) || (clone_flags & CLONE_STOPPED)) {
			/*
			 * We'll start up with an immediate SIGSTOP.
			 */
			sigaddset(&p->pending.signal, SIGSTOP);
			set_tsk_thread_flag(p, TIF_SIGPENDING);
		}

		if (!(clone_flags & CLONE_STOPPED))
			wake_up_new_task(p, clone_flags);
		else
			p->state = TASK_STOPPED;

		if (unlikely (trace)) {
			current->ptrace_message = nr;
			ptrace_notify ((trace << 8) | SIGTRAP);
		}

		if (clone_flags & CLONE_VFORK) {
			wait_for_completion(&vfork);
			if (unlikely (current->ptrace & PT_TRACE_VFORK_DONE)) {
				current->ptrace_message = nr;
				ptrace_notify ((PTRACE_EVENT_VFORK_DONE << 8) | SIGTRAP);
			}
		}
	} else {
		free_pid(pid);
		nr = PTR_ERR(p);
	}
	return nr;
}
Other operating systemsオペレーティングシステム treat processプロセス creation and program execution (and, in conjunction, the shell) very differently from Unix; in fact, Unix's approach often seems weird when you first encounter it. In the venerable VMS (Virtual Memory仮そう記録 System) from Digital Equipment Corporation (now owned by HP), executing a program loads the program into memory without replacing or overwriting the memory for DCL, the Digital Command Language. DCL resides in a special portion of memory, and is always present throughout the life of the processプロセス. This is handy when you want to be able to call function機能・関数s such as DCL's command line editor, but most of the time is wasteful of address space, and possibly other resources. Processプロセス creation in Unix is a heavy, complicated processプロセス, but not nearly as bad as in VMS, so in VMS great pains are taken to make processプロセス creation be a rare event.

Threads

So far, we have discussed a processプロセス as if it involves only a single program, running from begin to end. For many processプロセスes, this is accurate. However, modern OSes support multiple threads of control in a single processプロセス.

A processプロセス is an abstraction of both memory and the CPU. It contains one or more threads. The thread is the abstraction of the CPU, including the PC (program counter) and all of the registers. The stack is part of the thread, since its state depends on the current place in the program where you are running. Thus, separate threads place their local frames (local variables for a function機能・関数) on separate stacks, but memory in the heap and statically-allocated global variables are shared.

Threads can be implemented by the kernelカーネル itself, or in user space. User space implementation実装s are lighter weight, and may use a threads library that is itself portable, providing more portable software. User threads also allow the user to control scheduling.

The POSIX standard defines an API and semantics for threads. Here is some information情報 from the Linux man (manual) page for pthreads:

PTHREADS(7)                Linux Programmer’s Manual               PTHREADS(7)

名前
       pthreads - POSIX スレッド

説明
       POSIX.1 は、一般に POSIX スレッドや Pthreads として知られるスレッド・プ
       ログラミングのインタフェース群 (関数、ヘッダファイル) を規定している 。
       一 つのプロセスは複数のスレッドを持つことができ、全てのスレッドは同じプ
       ログラムを実行する。これらのスレッドは同じ大域メモリ (データとヒープ 領
       域) を共有するが、各スレッドは自分専用のスタック (自動変数) を持つ。

       POSIX.1  はスレッド間でどのような属性を共有するかについても定めている (
       つまり、これらの属性はスレッド単位ではなくプロセス全体で共通である):

       -  プロセス ID

       -  親プロセス ID

       -  プロセスグループ ID とセッション ID

       -  制御端末

       -  ユーザ ID とグループ ID

       -  オープンするファイルディスクリプタ

       -  レコードのロック (fcntl(3) 参照)

       -  シグナルの配置

       -  ファイルモード作成マスク (umask(2))

       -  カレント・ディレクトリ (chdir(2)) とルート・ディレクトリ (chroot(2))

       -  インターバル・タイマ (setitimer(2)) と POSIX タイマ (timer_create())

       -  nice 値 (setpriority(2))

       -  リソース制限 (setrlimit(2))

       -  CPU 時間 (times(2)) とリソース (getrusage(2)) の消費状況の計測

       スタックについても、POSIX.1 はどのような属性が個々のスレッドで独立に 管
       理されるかを規定している:

       -  スレッド ID pthread_t データ型)

       -  シグナルマスク (pthread_sigmask())

       -  errno 変数

       -  代替シグナルスタック (sigaltstack(2))

       -  リ ア ル タイム・スケジューリングのポリシーと優先度 (sched_setsched-
          uler(2) と sched_setparam(2))

       以下の Linux 特有の機能もスレッド単位である:

       -  ケーパビリティ (capabilities(7) 参照)

       -  CPU affinity (親和度) (sched_setaffinity(2))



PTHREADS(7)                Linux Programmer's Manual               PTHREADS(7)

NAME
       pthreads - POSIX threads

DESCRIPTION
       POSIX.1  specifies  a  set  of interfaces (function機能・関数s, header files) for
       threaded programming commonly known as POSIX threads, or  Pthreads.   A
       single processプロセス can contain multiple threads, all of which are executing
       the same program.  These threads share the same global memory (data and
       heap  segments),  but  each  thread  has its own stack (automatic vari-
       ables).

       POSIX.1 also requires that threads share a range  of  other  attributes
       (i.e., these attributes are processプロセス-wide rather than per-thread):

       -  processプロセス ID

       -  parent processプロセス ID

       -  processプロセス group ID and session ID

       -  controlling terminal端末

       -  user and group IDs

       -  open file descriptors

       -  record locks (see fcntl(2))

       -  signal dispositions

       -  file mode creation mask (umask(2))

       -  current directory (chdir(2)) and root directory (chroot(2))

       -  interval timers (setitimer(2)) and POSIX timers (timer_create())

       -  nice value (setpriority(2))

       -  resource limits (setrlimit(2))

       -  measurements of the consumption of CPU time (times(2)) and resources
          (getrusage(2))

       As well as the stack, POSIX.1 specifies that various  other  attributes
       are distinct for each thread, including:

       -  thread ID (the pthread_t data type)

       -  signal mask (pthread_sigmask())

       -  the errno variable

       -  alternate signal stack (sigaltstack(2))

       -  real-time  scheduling policy and priority (sched_setscheduler(2) and
          sched_setparam(2))

       The following Linux-specific features are also per-thread:

       -  capabilities (see capabilities(7))

       -  CPU affinity (sched_setaffinity(2))


Working with threads is very much like writing code for multitasking embedded組込み用 operating systemsオペレーティングシステム, such as, say, Nucleus or VxWorks, and as such are a very important concept, and learning to use them is valuable. However, synchronization同期 bugs are common; libraries that simplify locking are very useful, but often so conservative that it is difficult for more than one thread at a time to run. When well-managed, threads allow for highly efficient shared-memory multiprocessプロセスing. However, the trend in parallel processプロセスing is toward message passing systems, which obviously map well to distributed分散-memory multicomputers as well as the Internet itself.

Kernelカーネル Processプロセス Management管理

We aren't going into detail on this topic at the moment, but a few basic concepts are in order. A Unix (or Linux) kernelカーネル manages the kernelカーネル structures described above in a doubly-linked list (is that kept in some kind of order? not sure). Individual processプロセスes are named via their PID, or processプロセス ID. Because each processプロセス has exactly one parent, and any processプロセス can create one or more children, the processプロセスes in a system are structured in a processプロセス tree. A (sub-)tree of processプロセスes can all be managed as a group. One consequence of the requirement that a processプロセス must have a parent is that no processプロセス with children can be completely destroyed until all of its children have exited.

A very useful modern innovation in Unix-style operating systemsオペレーティングシステム is the /proc file system. By looking in the directory /proc, one can find out many facts about the running state of the entire system and of individual processプロセスes.

Signals, Interrupt割り込みs, and Exits

Signals, as Unix terms them, are the most fundamental way of letting a processプロセス know that something has happened in the system. They may result from some action of the processプロセス itself, such as a floating point exception or an illegal instruction, or may be sent from one processプロセス to another using the system callシステムコール kill(). kill() might seem like an odd name, but signal() is already taken as the system callシステムコール a processプロセス uses to install its own signal handler, and kill() is most often used to actually kill a running program.

       最初に、POSIX.1-1990 に定義されているシグナルを示す。

       シグナル      値      動作   コメント
       ------------------------------------------------------------------------
       SIGHUP         1      Term   制御端末(controlling terminal端末)のハングアッ
                                    プ検出、または制御しているプロセスの死
       SIGINT         2      Term   キーボードからの割り込み (Interrupt割り込み)
       SIGQUIT        3      Core   キーボードによる中止 (Quit)
       SIGILL         4      Core   不正な命令
       SIGABRT        6      Core   abort(3) からの中断 (Abort) シグナル
       SIGFPE         8      Core   浮動小数点例外
       SIGKILL        9      Term   Kill シグナル
       SIGSEGV       11      Core   不正なメモリ参照
       SIGPIPE       13      Term   パイプ破壊: 読み手の無いパイプへの書き出し
       SIGALRM       14      Term   alarm(2) からのタイマーシグナル
       SIGTERM       15      Term   終了 (termination) シグナル
       SIGUSR1    30,10,16   Term   ユーザ定義シグナル 1
       SIGUSR2    31,12,17   Term   ユーザ定義シグナル 2
       SIGCHLD    20,17,18   Ign    子プロセスの一旦停止 (stop) または終了
       SIGCONT    19,18,25   Cont   一旦停止 (stop) からの再開
       SIGSTOP    17,19,23   Stop   プロセスの一旦停止 (stop)
       SIGTSTP    18,20,24   Stop   端末 (tty) より入力された一旦停止 (stop)
       SIGTTIN    21,21,26   Stop   バックグランドプロセスの tty 入力
       SIGTTOU    22,22,27   Stop   バックグランドプロセスの tty 出力


       シグナル SIGKILL と SIGSTOP はキャッチ、ブロック、無視できない。

       次に、 POSIX.1-1990 標準にはないが、 SUSv2 と POSIX.1-2001 に記述されて
       いるシグナルを示す。

       シグナル       値      動作   コメント
       -----------------------------------------------------------------
       SIGBUS      10,7,10    Core   バスエラー (不正なメモリアクセス)
       SIGPOLL                Term   ポーリング可能なイベント (Sys V)。
                                     SIGIOと同義
       SIGPROF     27,27,29   Term   profiling タイマの時間切れ
       SIGSYS      12,-,12    Core   ルーチンへの引数が不正 (SVr4)
       SIGTRAP        5       Core   トレース/ブレークポイント トラップ
       SIGURG      16,23,21   Ign    ソケットの緊急事態 (urgent  condi-
                                     tion) (4.2BSD)
       SIGVTALRM   26,26,28   Term   仮想アラームクロック (4.2BSD)
       SIGXCPU     24,24,30   Core   CPU時間制限超過 (4.2BSD)
       SIGXFSZ     25,25,31   Core   ファイルサイズ制限の超過 (4.2BSD)

      First the signals described in the original POSIX.1-1990 standard.

       Signal     Value     Action   Comment
       -------------------------------------------------------------------------
       SIGHUP        1       Term    Hangup detected on controlling terminal端末
                                     or death of controlling processプロセス
       SIGINT        2       Term    Interrupt割り込み from keyboard
       SIGQUIT       3       Core    Quit from keyboard
       SIGILL        4       Core    Illegal Instruction
       SIGABRT       6       Core    Abort signal from abort(3)
       SIGFPE        8       Core    Floating point exception
       SIGKILL       9       Term    Kill signal
       SIGSEGV      11       Core    Invalid memory reference
       SIGPIPE      13       Term    Broken pipe: write to pipe with no readers
       SIGALRM      14       Term    Timer signal from alarm(2)
       SIGTERM      15       Term    Termination signal
       SIGUSR1   30,10,16    Term    User-defined signal 1
       SIGUSR2   31,12,17    Term    User-defined signal 2
       SIGCHLD   20,17,18    Ign     Child stopped or terminated
       SIGCONT   19,18,25    Cont    Continue if stopped
       SIGSTOP   17,19,23    Stop    Stop processプロセス
       SIGTSTP   18,20,24    Stop    Stop typed at tty
       SIGTTIN   21,21,26    Stop    tty input for background processプロセス
       SIGTTOU   22,22,27    Stop    tty output for background processプロセス

       The  signals SIGKILL and SIGSTOP cannot be caught, blocked, or ignored.

       Next the signals not in the  POSIX.1-1990  standard  but  described  in
       SUSv2 and POSIX.1-2001.

       Signal       Value     Action   Comment
       -------------------------------------------------------------------------
       SIGBUS      10,7,10     Core    Bus error (bad memory access)
       SIGPOLL                 Term    Pollable event (Sys V). Synonym of SIGIO
       SIGPROF     27,27,29    Term    Profiling timer expired
       SIGSYS      12,-,12     Core    Bad argument to routine (SVr4)
       SIGTRAP        5        Core    Trace/breakpoint trap
       SIGURG      16,23,21    Ign     Urgent condition on socket (4.2BSD)
       SIGVTALRM   26,26,28    Term    Virtual alarm clock (4.2BSD)
       SIGXCPU     24,24,30    Core    CPU time limit exceeded (4.2BSD)
       SIGXFSZ     25,25,31    Core    File size limit exceeded (4.2BSD)

 
Processプロセスes can catch many of the signals that are sent to them, resulting in a particular signal handler being run. Such a signal handler may, for example, reread a configuration file (this is a common desire, and is usually triggered via the SIGHUP signal). Signals that are not caught generally result in the processプロセス exiting.

Summary

We will see all of these topics again when we discuss virtual memory仮そう記録 and processプロセス scheduling. We will also discuss them in the context of parallel processプロセスing.

Homeworkかだい

This week's homeworkかだい:

  1. This week we have talked about processプロセスes. Write a program to call fork() repeatedly. Eventually, the call will fail in one of the children. When it does, print out the depth of the processプロセス tree: how many times have you succeeded in calling fork()? What was the reason for the failure?
  2. Now modify to collect timing information情報 for a given number of processプロセスes, giving the number of processプロセスes as an argument to the program (no argument should do the same as above, run until the fork fails). How long does it take to create and delete a thousand processプロセスes? Two thousand?
  3. Do BOTH of the following:
    1. Find the Linux kernelカーネル code for fork() and post it on your blog. If your machine is Linux, you may want to learn where the source code is stored on your machine (you may have to install it); if you are not using Linux, you may use one of the browsable Linux kernelカーネル source archives on the web (there are several; pick one).
    2. Find the definition of the processプロセス or task structure from another operating systemオペレーティングシステム, either in a book or online. Post it on your blog. Over the next few weeks, we will compare this structure to Linux. You can find the definition for BSD, Windows, Symbian, NACHOS, Minix, or any other OS of your choice.
  4. Determine how many processプロセスes have been created on your computer since the last time it was booted. Describe any caveats on your knowledge.

Next Lecture

Next lecture:

第4回 5月13日 プロセス間通信
Lecture 4, May 13: Inter-processプロセス Communication通信 We will also cover synchronization同期 and introduce deadlock.

Readings for next week:

The following week we will discuss processプロセス scheduling, including multiprocessプロセスor scheduling and the idea of processプロセスor affinity for threads and processプロセスes.

Ken Thompson, Butler Lampson, Jim Gray, Nikalus Wirth, from Berkeley

その他 Additional Information情報