Управление процессами - 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;
Контекст безопасности процесса
/*
* 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;
/*
* COW Supplementary groups list
*/
struct group_info {
atomic_t usage;
int ngroups;
kgid_t gid[0];
} __randomize_layout;
Виртуальная файловая система и пространство имён
/* Filesystem information: */
struct fs_struct *fs;
Маска создания файлов 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;
/*
* 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
.
Лабораторные работы
Ссылки:
- Структура task_struct
- Структура cred
- Credentials in Linux
- Michael Kerrisk. The Linux Programming Interface. October 2010. ISBN-13: 978-1-59327-220-3. Главы 6,7.
- У. Ричард Стивенс, Стивен Раго. UNIX. Профессиональное программирование. Главы 7,8,9.
- Роберт Лав. Ядро Linux: описание процесса разработки.