Lecture
A process is a program at the time of execution. The key concept of the operating system. The concept of address space is associated with the process . An address space is a list of addresses in memory from a certain minimum to a maximum that the process can read and write to. Address space = program + data + stack. Accordingly, a set of registers is associated with the process: a stack pointer, a command counter, etc.
Information about the processes needed to restart it is stored in the process table.
A suspended process consists of its own address space — an image of the memory and a component of the process table, which contains among other things (for example, pointers to positions in files where the process was stopped) its registers.
Switching between processes is called multitasking or multiprogramming. In fact, there is only one physical instruction counter into which the logical counter of instructions of the current process is loaded. When the time allotted to the current process ends, the physical instruction counter is stored in the logical instruction counter of the process in memory.
In universal systems, a way to create and interrupt processes as needed is needed. Consider some ways to solve this problem. Events leading to the creation of processes:
1 ) System initialization . When booting the OS, several processes are created. High priority: user interaction and desired work. Background: mail, requests for web-pages, news, printing, are called demons. In large systems, dozens of demons. In UNIX: the ps command lists the running processes. In Windows 2000, CTRL-ALT-DEL calls the task manager.
2) Execution of a process creation request issued by a running process. It is useful when the task being performed is formed as a set of related but independent interacting processes. For example, sampling a large amount of data from a network; one process selects data and places it in a shared buffer; the second reads the data from the buffer and processes it.
3) User request to create a process . In interactive systems, the user runs a command from the command line or by clicking on the icon. The result is the creation of a new process and the launch of a program in it. For example, when UNIX runs X-Windows, the new process receives the window in which it was launched. In Windows 2000, the process does not have its own window, but it must create several windows. In both systems, the user can open several windows, each of which has its own process.
4) Initiating the batch job. Users send a batch job (possibly from remote access), and the OS creates a new process and starts the next task from the queue when the necessary resources are released.
From a technical point of view, in all the above cases a new process is formed in the same way: the current process fulfills a request to create a new process.
In UNIX, the only call to fork that creates a duplicate of a process, both the parent and the child processes have the same memory image, open files. The child process makes an execve call to change the memory image and start a new program. An example, starting the sort program , the shell creates a child process by branching, which executes the sort program. The meaning of this two-step process is that the child process has time to process the file description after the fork , but before execve , in order to redirect the standard input and output devices and the error message stream.
In Windows, calling only one CreateProcess Win32 interface manages both the creation of the process and the launch of the necessary program in it. This function has 10 parameters (the name of the program being started, the command line parameters of this program, various security attributes, bits that control the inheritance of open files, priorities, window specification, pointer to structure - process information for the calling program.) In addition, there are about 100 functions for managing processes and their synchronization.
In UNIX, the starting address space is a copy of the parent, but the rewritable memory is not shared. At the same time, the created process can share with the parent some resources, for example, open files.
In Windows, the address spaces of the parent and child processes differ from the beginning.
Reasons for completing the process:
1) Normal output . Processes are completed as their work. After the program is compiled, the compiler executes a system request to inform the operating system that it is finished. On UNIX, this is exit-request, Windows-ExitProcess. 2) Error (intentionally). In editors, browsers and other programs of this type there is a button or menu item - deleting temporary files, completing the process.
3) Exit by unrecoverable error (unintentionally). For example, compiling a file that does not exist. Interactive processes do not shut down when receiving the wrong parameters, asking the user to enter the correct parameters. In addition, an error in the program: division by zero, access to a non-existent memory area, execution of an invalid command.
4) Execution by other process of system request for destruction. UNIX - kill, Win 32 - TerminateProcess. In both cases, the killer must have the appropriate powers in relation to the "kill" process. In some systems, upon completion of the process, all processes created by it are terminated; but this does not apply to UNIX or to Windows.
In UNIX, processes form a hierarchy of processes. A process can have only one parent and any number of descendants. In UNIX, a process and all its descendants form a group of processes . The signal sent by the user from the keyboard (CTRL_ALT_DEL) is delivered to all members of the group interacting with the keyboard at the moment (usually these are all active processes created in the current window). Each of the processes can intercept a signal, ignore it, process it by default.
Process hierarchy example: UNIX initialization at startup. The boot image has a special init process that reads a file storing the number of terminals. Then the process is branched so that each terminal corresponds to one process. Processes wait for any user to log in. Thus, all processes in the system belong to a single tree, starting init.
In Windows, there is no concept of a hierarchy of processes, and all processes are equal. The only thing that manifests itself in the hierarchy is the creation of a process in which the parent process receives a special marker that allows it to control the child process. But the marker can be transferred to another process, breaking the hierarchy. On UNIX, this is not possible.
Example: cat chapter1 chapter2 chapter3 | grep tree. The first process executing the cat file combines and outputs three files. The second process executing the grep file selects all the lines containing the word "tree". Depending on the remaining speeds, it may turn out that grep is already ready to start, but there is no input data for this process yet. The process is blocked until data is received.
The second reason for the shutdown is the decision of the operating system scheduler. These two situations are fundamentally different.
Three possible process states:
1. Working (using the processor at this particular moment)
2. Ready to work (temporarily suspended to allow another process to do the work;
3. Blocked (the process cannot be started before some external event occurs).
|
|||
Fig. 3.1. The process can be in working, ready and locked state. Arrows indicate possible transitions between states .
The considered approach is described by the model presented in fig. 3.2.
Processes |
||||
0 |
one |
... |
n - 2 |
n - 1 |
Scheduler |
Fig. 3.2. Lower
The lower level of the operating system is the scheduler, and there are many processes on the upper levels. All interrupt handling and the details associated with stopping and starting processes are hidden in what we call the scheduler, which is essentially a very small program. The rest of the OS is structured as a set of processes.
To implement the process model, the OS contains a table, called a process table, with one element for each process. An element of the table contains information about the process status, instruction counter, stack pointer, memory allocation, open file status, resource usage and allocation, etc., in general, everything that needs to be stored when switching to the ready or blocking state for later launch as if the process did not stop.
Table 3.1 Some fields of a typical process table element
Process control |
Memory management |
File management |
Registers |
Pointer to text segment |
Root directory |
Command counter |
Pointer to the data segment |
Working directory |
Stack pointer |
Pointer to stack segment |
File descriptors |
Memory status |
|
User ID |
A priority |
|
Group id |
Scheduling options |
|
|
Process id |
|
|
Parent process |
|
|
Process group |
|
|
Signals |
|
|
Process start time |
|
|
CPU time used |
|
|
Child processor time |
|
|
Next alarm time |
|
|
Table 3.2. Interrupt low level OS interrupt handling scheme
one |
Hardware preserved. In command stack |
2 |
AO loads new command counter from OP vector (interrupt handling) |
3 |
Assembly procedure saves registers |
four. |
The assembly procedure sets a new stack. |
five. |
The interrupt handling program in C starts. (Usually it reads and buffers input data) |
6 |
The scheduler selects the next process. |
7 |
The C program transfers the procedure to the procedure in assembler |
eight. |
The assembler procedure starts a new process. |
UNIX is a multitasking system , i.e. several independent processes can work simultaneously. Each user can have several active processes at the same time, so that hundreds and even thousands of processes can operate simultaneously in a large system.
An example of a typical daemon cron daemon - wakes up once a minute and checks if it needs to be done. Plans work for minutes, hours days and even months ahead. If you need a reminder, leave an entry in the cron daemon database so that it squeaks on the right day at the right time.
In addition, the cron daemon is used to periodically run tasks, for example, for daily disk archiving at 4 am.
Other daemons control outgoing e-mail, queues to the printer, check if there are enough free memory pages and so on. Implemented in UNIX is quite simple: every daemon is an independent process.
Creating a process by calling fork , which creates an exact copy of the parent process, the newly created process is called a child . The parent and child processes have their own memory images. If the parent process subsequently changes its variables, these changes are not visible to the child, and vice versa.
Open files are shared by parent and child processes. If any file was opened before the fork was called , it remains open in both processes and further.
If the memory images, registers, and everything else of the parent and child processes are identical, then how to determine which of them executes the parent program, and which child program. A call to fork returns 0 to the child process , and a non-zero PID to the parent process .
Listing 3.1 Creating a process on a UNIX system
pid = fork ();
if (pid <0) {
handle_error ();
} else if (pid> 0) {
}
else {
}
#include
#include
#include
#include
int main ()
{
pid_t n;
switch (n = fork ()) {
case (n == - 1): perror (“fork”); / * fork fails * /
break;
case (n == 0): cout << ”Child process created \ n”;
return 0;
default : cout << “Parent process after work \ n”;
}
return 0; }
Processes are recognized by their PID identifiers. When creating a process its PID
handed to parent. If the child process wants to know its PID, getpid. Process identifiers are used in a different way, for example, when a process terminates, its PID is given to the parent, because the parent can have many child processes.
In a UNIX system, processes can communicate with each other using one of the types of messaging - message queuing. You can create a pipe between two processes, in which one process will write a stream of bytes, and another process can read it. Process synchronization is achieved by blocking the process when trying to read data from an empty channel. When data appears in the channel - the process is unlocked.
With the help of channels are organized conveyors shell. When a shell sees a line like sort < f | head , it creates two processes, sort and head , and also establishes a channel between them in such a way that the standard output stream of the sort command is the standard input stream of the head command . In this case, all the data generated by the sort program , go directly to the head , which does not require a temporary file. If the channel becomes full, the system suspends the sort program until head deletes at least some data.
In addition, processes can communicate using software interrupts, called signals . The process has a choice: to ignore the signal, intercept or allow the signal to kill the process (the default action for most signals). If the process chooses to intercept signals, then it must specify the signal processing procedures. Signal processing is similar to the hardware interrupt procedure. A process can send signals only to members of its process group, consisting of:
A) his parent's group;
B) all grandparents;
C) brothers, sisters;
D) children, (grandchildren and great-grandchildren).
A process can send a signal to the whole group at once in one system call.
Signals are also used for other purposes, for example, if a process performs floating-point calculations and divides a number by 0, it will receive a SIGFPE (Floating PointExeption Signal) signal.
Table 3.3. Signals required by the POSIX standard
Signal |
Cause |
SIGALARM |
The onset of the signal timer timeout. API alarm () can be generated. |
Sigabrt |
Emergency shutdown process. The abort () API may be generated. |
SIGFPE |
Invalid math operation |
SIGHUP |
Disconnection with the terminal manager. The modem hung up the phone line used by the process. |
Sigill |
The user pressed the DEL key to interrupt the process. |
SIGQUIT |
Out of the process. Usually generated combo. CL. [Ctrl + \] |
Sigkill |
Process destruction |
Sigpipe |
Attempting to write invalid channel |
SIGSEGV |
Segmentation error. May be generated by dereference |
Sigterm |
Process completion |
SIGUSR1 |
Reserved and user defined |
Sigusr2 |
Reserved and user defined
|
System calls for process management in UNIX
Table 3.4. Some process related system calls
System call |
Description |
pid = fork () |
Create a child process identical to the parent |
pid = waitpid (pid, & statloc, opts) |
Wait for the child to complete |
s = execve (name, argv, envp) |
Replace process memory image |
exit (status) |
Replace process execution and return status |
s = sigaction (sig, & act, & oldact) |
Determine the actions performed by the arrival of the signal |
s = sigreturn (sig, & act, & oldact) |
Return control after signal processing |
s = sigprocmask (how, & set, & old) |
Examine or change signal mask |
s = sigpending (set) |
Get or set blocked signals |
s = kill (pid, sig) |
Send a signal to the process |
res = alarm (seconds) |
Set alarm |
s = pause () |
Suspend the process until the next signal |
fork () is the only way to create new processes on UNIX systems. As a rule, the child process executes a program different from the parent. For example, the shell program ... (an example from Robachevsky). To wait for the completion of the child process, the parent process calls the waitpid (...) system call . The first parameter is the pidprocess, the completion of which is expected; if you specify -1, the system call expects the completion of any child process. The second parameter is the address of the variable storing the completion status of the process. The third parameter determines whether the waitpid process calling the system call will be blocked until the child process is completed, or it will immediately receive control after the system call is accessed.
In the most general case, the exec system call has three parameters: the name of the executable file, a pointer to an array of arguments, and a pointer to an array of environment strings. Various variants of this procedure execve , execl , execv , execl e allow you to omit certain parameters. All these procedures address the same system call. Хотя сам системный вызов называется exec , библиотечной процедуры с таким именем нет. Что касается третьего параметра: envp , он представляет собой указатель на переменные среды и является массивом, содержащим строки вида имя=значение , используемые в программе для передачи такой информации, как тип терминала и имя рабочего каталога.
Простой системный вызов exit , у него один параметр - статус выхода (0..255), возвращаемый родительскому процессу в переменной status системного вызова waitpid . Младший байт переменной статус содержит статус завершения 0 – нормальное завершение или код ошибки – аварийное завершение. Например, если родительский процесс выполняет оператор:
n=waitpid (-1, &status, 0);
он будет приостановлен до тех пор, пока не завершится какой-нибудь дочерний процесс. Если дочерний процесс завершится со статусом , скажем, равным 4, в качестве параметра библиотечной процедуры exit, то родительский процесс получит PID дочернего процесса и значение статуса, равное 0x400 . Младший байт переменной status относится к сигналам, старший байт представляет собой значение, задаваемое дочерним процессом в виде параметра при обращении к системному вызову exit.
Если процесс уже завершил свою работу, а родительский процесс не ожидает этого события, то дочерний процесс переводится в так называемое состояние зомби . Он не занимает ресурсов процессора, но существует как запись в таблице процессов.
Программа создает порожденный процесс, который подтверждает свое создание, а затем завершается с кодом завершения 15. Тем временем родительский процесс приостанавливает свое выполнение посредством вызова waitpid. После завершения порожденного процесса выполнение родительского возобновляется, и его переменным status и child_pid присваивается код завершения порожденного процесса, а также его идентификатор. Родительский процесс использует макросы, определенные в < sys/ wait. h>, для определения статуса выполнения порожденного процесса следующим способом:
Если WIFEXITED возвращает ненулевое значение, следовательно, порожденный процесс был завершен с использованием вызова _exit. Родительский процесс извлекает код завершения (который в этом примере равен 15) с помощью макрокоманды WEXITSTATUS. Затем он направляет полученное значение в стандартный поток ошибок.
Если WIFEXITED возвращает нулевое значение, а WIFSTOPPED – ненулевое, следовательно, порожденный процесс был завершен сигналом. Родительский процесс извлекает номер сигнала с помощью макрокоманды WSTOPSIG. Затем он направляет полученное значение в стандартный поток ошибок.
Если WIFEXITED и WIFSTOPPED возвращают нулевое значение, а WIFSIGNALED – ненулевое, то порожденный процесс был завершен неперехваченным сигналом. Родительский процесс извлекает номер сигнала с помощью макрокоманды WTERMSIG. Затем он направляет полученное значение в стандартный поток ошибок
Если WIFEXITED, WIFSTOPPED и WIFSIGNALED возвращают нулевые значения, то либо родительский процесс не имеет порожденных, либо waitpid был прерван сигналом. Поэтому родительский процесс вызывает функцию perror для вывода подробной диагностической информации о причинах неудачи.
Родительский процесс использует системные вызовы wait и wai t pid для перехода в режим ожидания завершения порожденного процесса и для выборки статуса его завершения (присвоенного порожденному процессу с помощью функции _ exit ). Кроме того, они освобождают ячейку для порожденного процесса в таблице процессов, с тем, чтобы она могла использоваться новым процессом. Прототипы этих функция выглядят так:
#include
pid_t wait(int * status_p);
pid_t waitpid(pid_t child_pid, int* status_p, int options);
Функция wait приостанавливает выполнение родительского процесса до тех пор, пока ему не буде послан сигнал, либо пока один из его порожденных процессов не завершится или не будет остановлен (а его статус не будет сообщен). Если порожденный процесс уже завершился и был остановлен до вызова wait , функция wait немедленно возвратится со статусом завершения порожденного процесса (его значение содержится в аргументе status_ p) , а возвращаемым значением функции будет PID порожденного процесса. Если, однако, родительский процесс не имеет порожденных процессов, завершения который он ожидает, или он был прерван сигналом при выполнении wait, the function returns a value of –1, and the variable errno will contain an error code. If the parent process has created more than one child process, the wait function will wait for each one to complete.
The waitpid function is more versatile than wait . As with the wait function , the waitpid function reports the completion code and the identifier of the child process after it has completed. However, in the case of waitpid in the calling process, you can indicate which of the spawned processes should be expected. To do this, you must assign one of the following values to the argument child_ pid :
Несколько СВ относятся к сигналам, используемым различными способами. Например, текстовый редактор отображает содержимое очень длинного текстового файла, Нажатие CTRL+C или DEL - редактору посылается сигнал, который прервет работу текстового редактора.
Чтобы заявить о своем желании перехватить тот или иной сигнал sigaction. Первый параметр этого системного вызова – сигнал, который требуется перехватить. Второй параметр – указатель, на структуру, в которой хранится указатель на процедуру обработки сигнала вместе с различными битами и флагами. Третий параметр – указатель на структуру, в которой система возвращает информацию о текущем обрабатываемом сигнале, на случай, если позднее его нужно будет восстановить.
Обработчик сигнала может выполняться сколько угодно долго. На практике обработка сигналов не занимает много времени. Когда процедура обработки сигнала завершает свою работу, она возвращается к той точке, в которой ее прервали.
Системный вызов sigaction может использоваться для игнорирования сигнала или, чтобы восстановить действие по умолчанию – уничтожение процесса.
Кроме того, послать сигнал, можно при помощи системного вызова kill – любому родственному процессу. Выбор названия kill не особенно удачен, так как в большинстве случаев он используется процессами не для уничтожения других процессов, а, наоборот, в надежде, что этот сигнал будет перехвачен и обработан соответствующим образом.
Во многих приложения реального времени бывает необходимо прервать процесс через определенный промежуток времени системный вызов alarm. Параметр этого системного вызова задает временной интервал, по истечении которого процессу посылается SIGALARM. У процесса в каждый момент времени может быть только один будильник. Например, если процесс обращается к системному вызову alarm с параметром 10 с, а 3с спустя снова обращается к нему с параметром 20с, то он получит только один сигнал через 20 с после второго системного вызова. Первый сигнал будет отменен вторым обращением к системному вызову alarm. Если параметр системного вызова alarm равен нулю, то такое обращение отменяет любой сигнал будильника. Если сигнала будильника не перехватывается , то действие по умолчанию заключается в уничтожении процесса. Технически возможно игнорирование такого сигнала, но нецелесообразно.
Иногда случается так, что процессу нечем заняться пока придет сигнал. Например, обучающая программа, тестирующая скорость реакции. Отобразив на экране некоторый текст, обращается к системному вызову alarm, чтобы система послала ей сигнал через 30с. Пока студент читает текст, у программы дел нет. Она может сидеть в коротком цикле, ничего не делая, но такая реализация будет напрасно расходовать время центрального процессора, которое может понадобиться фоновому процессу или другому пользователю. Лучшее решение – системный вызов pause , который указывает ОС приостановить работу процесса, пока не придет следующий сигнал.
4. What processes are included in the relatives process group?
5. The signal sent to the process goes to all its relatives. Where, then, is the signal from the keyboard CTRL + C, if you are working in the editor at this time?
6. The actions of the process upon receipt of the signal.
7. Definition of a zombie process.
8. Whether a blocked process is planned for execution.
9. Examples of programs when it is better to block the process while waiting for some actions and when it is better to leave it running in parallel.
Comments
To leave a comment
Operating Systems and System Programming
Terms: Operating Systems and System Programming