Управление процессами - efanov/mephi GitHub Wiki

Понятие процесса

Программа – это исполняемый файл, размещенный на диске.

Программа, находящаяся в процессе исполнения, называется процессом.

UNIX обеспечивает присвоение каждому процессу уникального числового идентификатора, который называется идентификатором процесса. Идентификатор процесса – всегда целое неотрицательное число.

a process is an abstract entity, defined by the kernel, to which system resources are allocated in order to execute a program

Максимальное количество процессов в системе

$ cat /proc/sys/kernel/pid_max 
32768

Жизненный цикл процесса

  • Жизненный цикл процесса (fork->exec->wait->exit).

  • Состояния процесса (R-SDK-T-Z). Выполнение процесса в режиме ядра и в режиме пользователя.

/* Used in tsk->state: */
#define TASK_RUNNING			0x0000
#define TASK_INTERRUPTIBLE		0x0001
#define TASK_UNINTERRUPTIBLE		0x0002
#define __TASK_STOPPED			0x0004
#define __TASK_TRACED			0x0008
/* Used in tsk->exit_state: */
#define EXIT_DEAD			0x0010
#define EXIT_ZOMBIE			0x0020
#define EXIT_TRACE			(EXIT_ZOMBIE | EXIT_DEAD)
/* Used in tsk->state again: */
#define TASK_PARKED			0x0040
#define TASK_DEAD			0x0080
#define TASK_WAKEKILL			0x0100
#define TASK_WAKING			0x0200
#define TASK_NOLOAD			0x0400
#define TASK_NEW			0x0800
#define TASK_STATE_MAX			0x1000

/* Convenience macros for the sake of set_current_state: */
#define TASK_KILLABLE			(TASK_WAKEKILL | TASK_UNINTERRUPTIBLE)
#define TASK_STOPPED			(TASK_WAKEKILL | __TASK_STOPPED)
#define TASK_TRACED			(TASK_WAKEKILL | __TASK_TRACED)

#define TASK_IDLE			(TASK_UNINTERRUPTIBLE | TASK_NOLOAD)
  • Флаги процесса

/*
 * Per process flags
 */
#define PF_IDLE			0x00000002	/* I am an IDLE thread */
#define PF_EXITING		0x00000004	/* Getting shut down */
#define PF_EXITPIDONE		0x00000008	/* PI exit done on shut down */
#define PF_VCPU			0x00000010	/* I'm a virtual CPU */
#define PF_WQ_WORKER		0x00000020	/* I'm a workqueue worker */
#define PF_FORKNOEXEC		0x00000040	/* Forked but didn't exec */
#define PF_MCE_PROCESS		0x00000080      /* Process policy on mce errors */
#define PF_SUPERPRIV		0x00000100	/* Used super-user privileges */
#define PF_DUMPCORE		0x00000200	/* Dumped core */
#define PF_SIGNALED		0x00000400	/* Killed by a signal */
#define PF_MEMALLOC		0x00000800	/* Allocating memory */
#define PF_NPROC_EXCEEDED	0x00001000	/* set_user() noticed that RLIMIT_NPROC was exceeded */
#define PF_USED_MATH		0x00002000	/* If unset the fpu must be initialized before use */
#define PF_USED_ASYNC		0x00004000	/* Used async_schedule*(), used by module init */
#define PF_NOFREEZE		0x00008000	/* This thread should not be frozen */
#define PF_FROZEN		0x00010000	/* Frozen for system suspend */
#define PF_KSWAPD		0x00020000	/* I am kswapd */
#define PF_MEMALLOC_NOFS	0x00040000	/* All allocation requests will inherit GFP_NOFS */
#define PF_MEMALLOC_NOIO	0x00080000	/* All allocation requests will inherit GFP_NOIO */
#define PF_LESS_THROTTLE	0x00100000	/* Throttle me less: I clean memory */
#define PF_KTHREAD		0x00200000	/* I am a kernel thread */
#define PF_RANDOMIZE		0x00400000	/* Randomize virtual address space */
#define PF_SWAPWRITE		0x00800000	/* Allowed to write to swap */
#define PF_NO_SETAFFINITY	0x04000000	/* Userland is not allowed to meddle with cpus_allowed */
#define PF_MCE_EARLY		0x08000000      /* Early kill for mce process policy */
#define PF_MUTEX_TESTER		0x20000000	/* Thread belongs to the rt mutex tester */
#define PF_FREEZER_SKIP		0x40000000	/* Freezer should not count it as freezable */
#define PF_SUSPEND_TASK		0x80000000      /* This thread called freeze_processes() and should not be frozen */

Дескриптор процесса


struct task_struct {
...
	/* -1 unrunnable, 0 runnable, >0 stopped: */
	volatile long			state;

	/*
	 * This begins the randomizable portion of task_struct. Only
	 * scheduling-critical items should be added above here.
	 */
	randomized_struct_fields_start

	void				*stack;
	atomic_t			usage;
	/* Per task flags (PF_*), defined further below: */
	unsigned int			flags;
	unsigned int			ptrace;

	int				on_rq;

	int				prio;
	int				static_prio;
	int				normal_prio;
	unsigned int			rt_priority;

	const struct sched_class	*sched_class;
	struct sched_entity		se;
	struct sched_rt_entity		rt;

	unsigned int			policy;
	int				nr_cpus_allowed;
	cpumask_t			cpus_allowed;

	struct sched_info		sched_info;

	struct list_head		tasks;

Адресное пространство процесса

	struct mm_struct		*mm;
	struct mm_struct		*active_mm;

Код возврата процесса

	int				exit_state;
	int				exit_code;
	int				exit_signal;
	/* The signal sent when the parent dies: */
	int				pdeath_signal;
	/* JOBCTL_*, siglock protected: */
	unsigned long			jobctl;


	/* Bit to tell LSMs we're in execve(): */
	unsigned			in_execve:1;
	unsigned			in_iowait:1;

Идентификаторы процесса

	pid_t				pid;
	pid_t				tgid;

	/*
	 * Pointers to the (original) parent process, youngest child, younger sibling,
	 * older sibling, respectively.  (p->father can be replaced with
	 * p->real_parent->pid)
	 */

	/* Real parent process: */
	struct task_struct __rcu	*real_parent;

	/* Recipient of SIGCHLD, wait4() reports: */
	struct task_struct __rcu	*parent;

	/*
	 * Children/sibling form the list of natural children:
	 */
	struct list_head		children;
	struct list_head		sibling;
	struct task_struct		*group_leader;

	u64				utime;
	u64				stime;

	u64				gtime;
	struct prev_cputime		prev_cputime;



	/* Monotonic time in nsecs: */
	u64				start_time;

	/* Boot based time in nsecs: */
	u64				real_start_time;

	/*
	 * executable name, excluding path.
	 *
	 * - normally initialized setup_new_exec()
	 * - access it with [gs]et_task_comm()
	 * - lock it with task_lock()
	 */
	char				comm[TASK_COMM_LEN];

	struct nameidata		*nameidata;

Сигналы процесса


	/* Signal handlers: */
	struct signal_struct		*signal;
	struct sighand_struct		*sighand;
	sigset_t			blocked;
	sigset_t			real_blocked;
	/* Restored if set_restore_sigmask() was used: */
	sigset_t			saved_sigmask;
	struct sigpending		pending;
	unsigned long			sas_ss_sp;
	size_t				sas_ss_size;
	unsigned int			sas_ss_flags;

	struct callback_head		*task_works;

	struct audit_context		*audit_context;
#ifdef CONFIG_AUDITSYSCALL
	kuid_t				loginuid;
	unsigned int			sessionid;
#endif
	struct seccomp			seccomp;

	/* Thread group tracking: */
	u32				parent_exec_id;
	u32				self_exec_id;

	/* Protection against (de-)allocation: mm, files, fs, tty, keyrings, mems_allowed, mempolicy: */
	spinlock_t			alloc_lock;

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

	struct wake_q_node		wake_q;

	/* Journalling filesystem info: */
	void				*journal_info;

	/* Stacked block device info: */
	struct bio_list			*bio_list;

	/* VM state: */
	struct reclaim_state		*reclaim_state;

	struct backing_dev_info		*backing_dev_info;

	struct io_context		*io_context;

	/* Ptrace state: */
	unsigned long			ptrace_message;
	siginfo_t			*last_siginfo;

	struct task_io_accounting	ioac;

};

Безопасность процесса


	/* Process credentials: */

	/* Tracer's credentials at attach: */
	const struct cred __rcu		*ptracer_cred;

	/* Objective and real subjective task credentials (COW): */
	const struct cred __rcu		*real_cred;

	/* Effective (overridable) subjective task credentials (COW): */
	const struct cred __rcu		*cred;

        struct seccomp			seccomp;

	/* Used by LSM modules for access restriction: */
	void				*security;

Контекст безопасности процесса

struct cred


/*
 * The security context of a task
 *
 * The parts of the context break down into two categories:
 *
 *  (1) The objective context of a task.  These parts are used when some other
 *	task is attempting to affect this one.
 *
 *  (2) The subjective context.  These details are used when the task is acting
 *	upon another object, be that a file, a task, a key or whatever.
 *
 * Note that some members of this structure belong to both categories - the
 * LSM security pointer for instance.
 *
 * A task has two security pointers.  task->real_cred points to the objective
 * context that defines that task's actual details.  The objective part of this
 * context is used whenever that task is acted upon.
 *
 * task->cred points to the subjective context that defines the details of how
 * that task is going to act upon another object.  This may be overridden
 * temporarily to point to another security context, but normally points to the
 * same context as task->real_cred.
 */
struct cred {
	atomic_t	usage;
#ifdef CONFIG_DEBUG_CREDENTIALS
	atomic_t	subscribers;	/* number of processes subscribed */
	void		*put_addr;
	unsigned	magic;
#define CRED_MAGIC	0x43736564
#define CRED_MAGIC_DEAD	0x44656144
#endif
	kuid_t		uid;		/* real UID of the task */
	kgid_t		gid;		/* real GID of the task */
	kuid_t		suid;		/* saved UID of the task */
	kgid_t		sgid;		/* saved GID of the task */
	kuid_t		euid;		/* effective UID of the task */
	kgid_t		egid;		/* effective GID of the task */
	kuid_t		fsuid;		/* UID for VFS ops */
	kgid_t		fsgid;		/* GID for VFS ops */
	unsigned	securebits;	/* SUID-less security management */
	kernel_cap_t	cap_inheritable; /* caps our children can inherit */
	kernel_cap_t	cap_permitted;	/* caps we're permitted */
	kernel_cap_t	cap_effective;	/* caps we can actually use */
	kernel_cap_t	cap_bset;	/* capability bounding set */
	kernel_cap_t	cap_ambient;	/* Ambient capability set */
#ifdef CONFIG_KEYS
	unsigned char	jit_keyring;	/* default keyring to attach requested
					 * keys to */
	struct key __rcu *session_keyring; /* keyring inherited over fork */
	struct key	*process_keyring; /* keyring private to this process */
	struct key	*thread_keyring; /* keyring private to this thread */
	struct key	*request_key_auth; /* assumed request_key authority */
#endif
#ifdef CONFIG_SECURITY
	void		*security;	/* subjective LSM security */
#endif
	struct user_struct *user;	/* real user ID subscription */
	struct user_namespace *user_ns; /* user_ns the caps and keyrings are relative to. */
	struct group_info *group_info;	/* supplementary groups for euid/fsgid */
	struct rcu_head	rcu;		/* RCU deletion hook */
} __randomize_layout;

struct group_info


/*
 * COW Supplementary groups list
 */
struct group_info {
	atomic_t	usage;
	int		ngroups;
	kgid_t		gid[0];
} __randomize_layout;

Виртуальная файловая система и пространство имён


	/* Filesystem information: */
	struct fs_struct		*fs;

struct fs_struct

Маска создания файлов umask


struct fs_struct {
	int users;
	spinlock_t lock;
	seqcount_t seq;
	int umask;
	int in_exec;
	struct path root, pwd;
} __randomize_layout;


	/* Open file information: */
	struct files_struct		*files;

	/* Namespaces: */
	struct nsproxy			*nsproxy;

struct files_struct


/*
 * Open file table structure
 */
struct files_struct {
  /*
   * read mostly part
   */
	atomic_t count;
	bool resize_in_progress;
	wait_queue_head_t resize_wait;

	struct fdtable __rcu *fdt;
	struct fdtable fdtab;
  /*
   * written part on a separate cache line in SMP
   */
	spinlock_t file_lock ____cacheline_aligned_in_smp;
	unsigned int next_fd;
	unsigned long close_on_exec_init[1];
	unsigned long open_fds_init[1];
	unsigned long full_fds_bits_init[1];
	struct file __rcu * fd_array[NR_OPEN_DEFAULT];
};

/*
 * The default fd array needs to be at least BITS_PER_LONG,
 * as this is the granularity returned by copy_fdset().
 */
#define NR_OPEN_DEFAULT BITS_PER_LONG

struct fdtable {
	unsigned int max_fds;
	struct file __rcu **fd;      /* current fd array */
	unsigned long *close_on_exec;
	unsigned long *open_fds;
	unsigned long *full_fds_bits;
	struct rcu_head rcu;
};

struct file {
	union {
		struct llist_node	fu_llist;
		struct rcu_head 	fu_rcuhead;
	} f_u;
	struct path		f_path;
	struct inode		*f_inode;	/* cached value */
	const struct file_operations	*f_op;

	/*
	 * Protects f_ep_links, f_flags.
	 * Must not be taken from IRQ context.
	 */
	spinlock_t		f_lock;
	enum rw_hint		f_write_hint;
	atomic_long_t		f_count;
	unsigned int 		f_flags;
	fmode_t			f_mode;
	struct mutex		f_pos_lock;
	loff_t			f_pos;
	struct fown_struct	f_owner;
	const struct cred	*f_cred;
	struct file_ra_state	f_ra;

	u64			f_version;
#ifdef CONFIG_SECURITY
	void			*f_security;
#endif
	/* needed for tty driver, and maybe others */
	void			*private_data;

#ifdef CONFIG_EPOLL
	/* Used by fs/eventpoll.c to link all the hooks to this file */
	struct list_head	f_ep_links;
	struct list_head	f_tfile_llink;
#endif /* #ifdef CONFIG_EPOLL */
	struct address_space	*f_mapping;
	errseq_t		f_wb_err;
} __randomize_layout
  __attribute__((aligned(4)));	/* lest something weird decides that 2 is OK */

Адресное пространство процесса

Команда size(1) выводит размеры (в байтах) сегментов кода, данных и bss. Например:


$ size /bin/sh
text data bss dec hex filename
619234 21120 18260 658614 a0cb6 /bin/sh

В четвертой и пятой колонках выводится общий размер всех трех сегментов в десятичном и шестнадцатеричном представлении соответственно.

http://man7.org/tlpi/code/online/dist/proc/mem_segments.c.html

All information related to the process address space is included in an object called the memory descriptor of type mm_struct . This object is referenced by the mm field of the process descriptor.

Адресное пространство процесса представляется в ядре в виде структуры данных, которая называется дескриптором памяти (memory descriptor). В этой структуре содержится вся информация, относящаяся к адресному пространству процесса. Дескриптор памяти представляется с помощью структуры mm_struct, которая определена в файле <linux/mm_types.h>.

https://elixir.bootlin.com/linux/v4.18/source/include/linux/mm_types.h#L337


struct mm_struct {
	struct vm_area_struct *mmap;		/* list of VMAs */
...
	unsigned long start_code, end_code, start_data, end_data;
	unsigned long start_brk, brk, start_stack;
	unsigned long arg_start, arg_end, env_start, env_end;
...

Linux implements a memory region by means of an object of type vm_area_struct

Области памяти (memory areas) представляются с помощью структуры vm_area_struct, которая определена в файле <linux/mm_types.h>. В ядре Linux области памяти часто называются областями виртуальной памяти (virtual memory area, или VMA). Структура vm_area_struct используется для описания одной непрерывной области памяти в данном адресном пространстве.

https://elixir.bootlin.com/linux/v4.18/source/include/linux/mm_types.h#L261


struct vm_area_struct {
	unsigned long vm_start;		/* Our start address within vm_mm. */
	unsigned long vm_end;		/* The first byte after our end address
					   within vm_mm. */

	/* linked list of VM areas per task, sorted by address */
	struct vm_area_struct *vm_next, *vm_prev;
...
	struct mm_struct *vm_mm;	/* The address space we belong to. */
	pgprot_t vm_page_prot;		/* Access permissions of this VMA. */
	unsigned long vm_flags;		/* Flags, see mm.h. */

	/*
	 * For areas with an address space and backing store,
	 * linkage into the address_space->i_mmap interval tree.
	 */
	struct {
		struct rb_node rb;
		unsigned long rb_subtree_last;
	} shared;

	/*
	 * A file's MAP_PRIVATE vma can be in both i_mmap tree and anon_vma
	 * list, after a COW of one of the file pages.	A MAP_SHARED vma
	 * can only be in the i_mmap tree.  An anonymous MAP_PRIVATE, stack
	 * or brk vma (with NULL file) can only be in an anon_vma list.
	 */
	struct list_head anon_vma_chain; /* Serialized by mmap_sem &
					  * page_table_lock */
	struct anon_vma *anon_vma;	/* Serialized by page_table_lock */

	/* Function pointers to deal with this struct. */
	const struct vm_operations_struct *vm_ops;

	/* Information about our backing store: */
	unsigned long vm_pgoff;		/* Offset (within vm_file) in PAGE_SIZE
					   units */
	struct file * vm_file;		/* File we map to (can be NULL). */
	void * vm_private_data;		/* was vm_pte (shared mem) */

	atomic_long_t swap_readahead_info;
#ifndef CONFIG_MMU
	struct vm_region *vm_region;	/* NOMMU mapping region */
#endif
#ifdef CONFIG_NUMA
	struct mempolicy *vm_policy;	/* NUMA policy for the VMA */
#endif
	struct vm_userfaultfd_ctx vm_userfaultfd_ctx;
} __randomize_layout;

Флаги


#define VM_READ		0x00000001	/* currently active flags */
#define VM_WRITE	0x00000002
#define VM_EXEC		0x00000004
#define VM_SHARED	0x00000008

Получить информацию


$ cat /proc/14975/maps
00400000-004dd000 r-xp 00000000 08:03 1182384                            /usr/bin/bash
006dd000-006de000 r--p 000dd000 08:03 1182384                            /usr/bin/bash
006de000-006e7000 rw-p 000de000 08:03 1182384                            /usr/bin/bash
006e7000-006ed000 rw-p 00000000 00:00 0 
00d75000-00f39000 rw-p 00000000 00:00 0                                  [heap]
7f352261b000-7f3522627000 r-xp 00000000 08:03 1216692                    /usr/lib64/libnss_files-2.17.so
7f3522627000-7f3522826000 ---p 0000c000 08:03 1216692                    /usr/lib64/libnss_files-2.17.so
7f3522826000-7f3522827000 r--p 0000b000 08:03 1216692                    /usr/lib64/libnss_files-2.17.so
7f3522827000-7f3522828000 rw-p 0000c000 08:03 1216692                    /usr/lib64/libnss_files-2.17.so
7f3522828000-7f352282e000 rw-p 00000000 00:00 0 
7f352282e000-7f3528d57000 r--p 00000000 08:03 1459088                    /usr/lib/locale/locale-archive
7f3528d57000-7f3528f1a000 r-xp 00000000 08:03 1182092                    /usr/lib64/libc-2.17.so
7f3528f1a000-7f3529119000 ---p 001c3000 08:03 1182092                    /usr/lib64/libc-2.17.so
7f3529119000-7f352911d000 r--p 001c2000 08:03 1182092                    /usr/lib64/libc-2.17.so
7f352911d000-7f352911f000 rw-p 001c6000 08:03 1182092                    /usr/lib64/libc-2.17.so
7f352911f000-7f3529124000 rw-p 00000000 00:00 0 
7f3529124000-7f3529126000 r-xp 00000000 08:03 1216061                    /usr/lib64/libdl-2.17.so
7f3529126000-7f3529326000 ---p 00002000 08:03 1216061                    /usr/lib64/libdl-2.17.so
7f3529326000-7f3529327000 r--p 00002000 08:03 1216061                    /usr/lib64/libdl-2.17.so
7f3529327000-7f3529328000 rw-p 00003000 08:03 1216061                    /usr/lib64/libdl-2.17.so
7f3529328000-7f352934d000 r-xp 00000000 08:03 1182429                    /usr/lib64/libtinfo.so.5.9
7f352934d000-7f352954d000 ---p 00025000 08:03 1182429                    /usr/lib64/libtinfo.so.5.9
7f352954d000-7f3529551000 r--p 00025000 08:03 1182429                    /usr/lib64/libtinfo.so.5.9
7f3529551000-7f3529552000 rw-p 00029000 08:03 1182429                    /usr/lib64/libtinfo.so.5.9
7f3529552000-7f3529574000 r-xp 00000000 08:03 1182085                    /usr/lib64/ld-2.17.so
7f352974c000-7f352974f000 rw-p 00000000 00:00 0 
7f3529769000-7f352976b000 rw-p 00000000 00:00 0 
7f352976b000-7f3529772000 r--s 00000000 08:03 1182396                    /usr/lib64/gconv/gconv-modules.cache
7f3529772000-7f3529773000 rw-p 00000000 00:00 0 
7f3529773000-7f3529774000 r--p 00021000 08:03 1182085                    /usr/lib64/ld-2.17.so
7f3529774000-7f3529775000 rw-p 00022000 08:03 1182085                    /usr/lib64/ld-2.17.so
7f3529775000-7f3529776000 rw-p 00000000 00:00 0 
7fff06105000-7fff06126000 rw-p 00000000 00:00 0                          [stack]
7fff0615e000-7fff06160000 r-xp 00000000 00:00 0                          [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0                  [vsyscall]

Или


$ pmap 14975
14975:   bash
0000000000400000    884K r-x-- bash
00000000006dd000      4K r---- bash
00000000006de000     36K rw--- bash
00000000006e7000     24K rw---   [ anon ]
0000000000d75000   1808K rw---   [ anon ]
00007f352261b000     48K r-x-- libnss_files-2.17.so
00007f3522627000   2044K ----- libnss_files-2.17.so
00007f3522826000      4K r---- libnss_files-2.17.so
00007f3522827000      4K rw--- libnss_files-2.17.so
00007f3522828000     24K rw---   [ anon ]
00007f352282e000 103588K r---- locale-archive
00007f3528d57000   1804K r-x-- libc-2.17.so
00007f3528f1a000   2044K ----- libc-2.17.so
00007f3529119000     16K r---- libc-2.17.so
00007f352911d000      8K rw--- libc-2.17.so
00007f352911f000     20K rw---   [ anon ]
00007f3529124000      8K r-x-- libdl-2.17.so
00007f3529126000   2048K ----- libdl-2.17.so
00007f3529326000      4K r---- libdl-2.17.so
00007f3529327000      4K rw--- libdl-2.17.so
00007f3529328000    148K r-x-- libtinfo.so.5.9
00007f352934d000   2048K ----- libtinfo.so.5.9
00007f352954d000     16K r---- libtinfo.so.5.9
00007f3529551000      4K rw--- libtinfo.so.5.9
00007f3529552000    136K r-x-- ld-2.17.so
00007f352974c000     12K rw---   [ anon ]
00007f3529769000      8K rw---   [ anon ]
00007f352976b000     28K r--s- gconv-modules.cache
00007f3529772000      4K rw---   [ anon ]
00007f3529773000      4K r---- ld-2.17.so
00007f3529774000      4K rw--- ld-2.17.so
00007f3529775000      4K rw---   [ anon ]
00007fff06105000    132K rw---   [ stack ]
00007fff0615e000      8K r-x--   [ anon ]
ffffffffff600000      4K r-x--   [ anon ]
 total           116984K

Получение информации о процессах

Файловая система procfs. Команды: ps, top, pgrep, pstree, w, uptime.

Управление заданиями

Понятия задания, сессии и управляющего терминала. Выполнение процесса в основном и фоновом режимах. Команды: jobs, fg, bg.

  • Системные вызовы: fork(), execve(), wait(), _exit(), kill().

http://man7.org/tlpi/code/online/dist/procexec/t_fork.c.html

  • Средства взаимодействия процессов. Сигналы. Реакция на получение сигнала. Игнорирование и перехват сигналов. Посылка сигналов с клавиатуры и программно. Команды: kill, killall, pkill, trap.

Лабораторные работы

  1. Лабораторная работа "Управление процессами"
  2. Лабораторная работа. Работа с процессами

Ссылки:

  1. Структура task_struct
  2. Структура cred
  3. Credentials in Linux
  4. Michael Kerrisk. The Linux Programming Interface. October 2010. ISBN-13: 978-1-59327-220-3. Главы 6,7.
  5. У. Ричард Стивенс, Стивен Раго. UNIX. Профессиональное программирование. Главы 7,8,9.
  6. Роберт Лав. Ядро Linux: описание процесса разработки.