Процессы Процесс программы и набор ресурсов, которые выделяются данной исполняемой программе.

advertisement
Процессы
Процесс – это исполняемый экземпляр
программы и набор ресурсов, которые
выделяются данной исполняемой программе.
Ресурсы:
• виртуальное адресное пространство;
• системные ресурсы –области физической памяти,
процессорное время, файлы, растровые изображения
и т.д.;
• модули процесса, то есть исполняемые модули,
загруженные (отображенные) в его адресное
пространство – основной загрузочный модуль,
библиотеки динамической компоновки, драйверы
устройств и т.д.;
• уникальный идентификационный номер, называемый
идентификатором процесса;
• потоки (по крайней мере, один поток).
Модель процесса:
Квант
времени
Поток A
Переклю
чение
процесс
ора
Квант
времени
Поток B
Переклю
чение
процесс
ора
Квант
времени
…………
Планировщик процессов.
Диспетчер процессов
• Сохранение контекста текущего потока,
регистров, стека и областей памяти.
• Определение очередного потока.
• Восстановление контекста очередного
потока.
t
Последовательность исполнения потоков в среде с
вытесняющей многозадачностью:
В системе определен квант времени (порядка
десятков миллисекунд) – процессорное время
выделяемое одному потоку (каждому - своё).
Длительность выполнения одного потока не
может превышать одного кванта. Когда это
время заканчивается, диспетчер процессов
переключает процессор на выполнение другого
потока. При этом состояние регистров, стека и
областей памяти – контекст потока,
сохраняется в стеке потока. Очередность
потоков определяется их состоянием и
приоритетом.
Состояние процессов:
Действие
1
Блокировка
1.
2.
3.
4.
3
4
2
Готовность
Процесс заблокирован в ожидании ввода.
Диспетчер выбирает другой процесс.
Диспетчер выбирает данный процесс.
Входные данные стали доступны.
Реализацией процессов является таблица
процессов, - линейный список (программно
реализованный, как массив структур).
Информация о процессах хранится в таблице
процессов и обновляется планировщиком
процессов.
Некоторые поля типичной записи таблицы
процессов:
Регистры
Счетчик команд
Указатель стека
Состояние процесса
Приоритет
Идентификатор
процесса
Родительский процесс
Время запуска
процессора
Использованное время
процессора
Корневой каталог
Рабочий каталог
Дескрипторы файлов
Идентификатор
пользователя
Создание процесса:
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
void oldman(); void recreation();
int main(){
pid_t child_pid, parent_pid;
int i=0;
fprintf(stdout, "Before RECREATION %i\n",
parent_pid=(int) getpid());
child_pid=fork();
while(i++<5)
if(child_pid!=0)
oldman();
else
recreation();
return 0;
}
#include <sys/types.h>
#include <unistd.h>
void oldman(){
fprintf(stdout, "I'm not yet dead! My ID is %i\n", (int) getpid());
}
void recreation(){
fprintf(stdout, "Who I am? My ID is %i\n", (int) getpid());
}
С точки зрения планировщика дочерний и
родительский процессы независимы:
ewgenij@linux-g5md:~/2011spring/Lect2> ./2
Before RECREATION 6169
I'm not yet dead! My ID is 6169
I'm not yet dead! My ID is 6169
I'm not yet dead! My ID is 6169
Who I am? My ID is 6170
I'm not yet dead! My ID is 6169
I'm not yet dead! My ID is 6169
Who I am? My ID is 6170
Who I am? My ID is 6170
Who I am? My ID is 6170
Who I am? My ID is 6170
ewgenij@linux-g5md:~/2011spring/Lect2> ./2
Before RECREATION 6154
I'm not yet dead! My ID is 6154
I'm not yet dead! My ID is 6154
Who I am? My ID is 6155
Who I am? My ID is 6155
Who I am? My ID is 6155
Who I am? My ID is 6155
Who I am? My ID is 6155
I'm not yet dead! My ID is 6154
I'm not yet dead! My ID is 6154
I'm not yet dead! My ID is 6154
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int main(){
pid_t child_pid, parent_pid;
double s=0.0;;
child_pid=fork();
if(child_pid!=0){
s+=3.14;
fprintf(stdout, "CHILD: %i s=%g &s=%u\n", (int) getpid(),s,&s);
}
else{
s+=2.72;
fprintf(stdout, "PARENT: %i s=%g &s=%u\n", (int) getpid(),s, &s);
}
return 0;
}
Output:
PARENT: 5404 s=2.72 &s=2309295864
CHILD: 5403 s=3.14 &s=2309295864
При создании процесса с помощью системного вызова
fork() копируется адресное пространство, - переменная s
имеет один и тот же адрес. Однако отображение на
физическую память для родительского и дочернего
процесса различно, - значения переменной s различны.
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int main(){
pid_t child_pid;
pid_t parent_pid;
double s=0.0;;
FILE* fp;
child_pid=fork();
fp=fopen("test.dat","a+");
if(child_pid!=0){
s+=3.14;
fprintf(fp, "CHILD: %i s=%g &s=%u fp=%u\n", (int) getpid(),
s, &s, fp);
}
else{
s+=2.72;
fprintf(fp, "PARENT: %i s=%g &s=%u fp=%u\n",(int) getpid(),
s, &s,fp);
}
fclose(fp);
return 0;
}
test.dat
PARENT: 5450 s=2.72 &s=760346688 fp=6299664
CHILD: 5449 s=3.14 &s=760346688 fp=6299664
Дескрипторы файлов при копировании сохраняются.
Создание процессов с помощью семейства системных
вызовов exec*:
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int main(int argc, char* argv[]){
fprintf(stdout, "Before child process creating: PARENT ID = %i\n",
(int) getpid());
execvp(argv[1], argv);
//execvp("ls", argv);
fprintf(stdout, "Everything is ignored!\n");
return 0;
}
Output:
./6ex
Before child process creating: PARENT ID = 5728
1 1.c 2 2.c 2.dat 3 3.c 4 4.c 5 5.c 6 6.c 6ex 6ex.c
test.dat
./6ex -l *.dat
Before child process creating: PARENT ID = 5741
-rw-r--r-- 1 ewgenij users 3157 2011-02-15 14:34 2.dat
-rw-r--r-- 1 ewgenij users 90 2011-02-15 15:37 test.dat
./6ex ./5
Before child process creating: PARENT ID = 5923
CHILD: 5923 s=3.14 &s=3669975528
PARENT: 5924 s=2.72 &s=3669975528
Совместное использование fork и execvp:
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int main(int argc, char* argv[]){
pid_t
child_pid;
child_pid=fork();
if( child_pid==0)
execvp("ls", argv);
fprintf(stdout,"The main program is yet running!\n");
return 0;
}
Родительский процесс продолжает существовать и активен:
ewgenij@linux-g5md:~/2011-spring/Lect2> ./7ex -l *.png
The main program is yet running!
-rw-r--r-- 1 ewgenij users 119000 2011-02-15 17:27 exec1.png
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <signal.h>
void oldman(){
fprintf(stdout, "I'm not yet dead! My ID is %i\n", (int) getpid());
}
void recreation(){
fprintf(stdout, "Who I am? My ID is %i\n", (int) getpid());
}
int main(){
pid_t child_pid, parent_pid;
int i=0;
fprintf(stdout, "Before RECREATION %i\n",
parent_pid=(int) getpid());
child_pid=fork();
while(i++<5)
if(child_pid!=0){
oldman();
if(i==3) kill(child_pid,SIGTERM);
}
else
recreation();
return 0;
}
I'm not yet dead! My ID is 6526
I'm not yet dead! My ID is 6526
I'm not yet dead! My ID is 6526
Who I am? My ID is 6527
Who I am? My ID is 6527
I'm not yet dead! My ID is 6526
I'm not yet dead! My ID is 6526
Интерфейс системных вызовов MS Windows
Win32
Особенности реализации языка С компании
Microsot (компилятор cl).
Некоторые типы данных, поддерживаемые
Microsoft Windows:
DWORD
BOOL
typedef unsigned long DWORD
typedef int BOOL;
BYTE
typedef unsigned char BYTE;
PVOID
typedef void *PVOID;
HANDLE
typedef PVOID HANDLE;
Чтобы обеспечить поддержку типов Microsoft
Windows в программе, необходимо включить в нее
заголовочный файл windows.h.
Этот файл также содержит объявления функций
интерфейса системных вызовов MS Windows Win32
API.
Пример объявления функции:
BOOL GetComputerName(
LPTSTR
lpBuffer;
LPDWORD nSize;
);
LPSTR
LPDWORD
typedef char *LPSTR
typedef WORD *LPDWORD
#include <windows.h>
#include <stdio.h>
int main(){
char Buffer[MAX_COMPUTERNAME_LENGTH+1];//[5];
int size=sizeof(Buffer);
if( !GetComputerName((LPTSTR)Buffer, (LPDWORD)&size) ){
printf("System error code: %i\n",GetLastError());
return -1;
}
fprintf(stdout,"The computer name is %s\n",Buffer);
return 0;
}
Аварийный выход (при задании размера
буфера равным 5):
C:\2011-spring\Лекции\Лекция2\Лаб2c>1
System error code: 111
Запись в таблице System Error Codes:
110….……………………………………………………1
11
ERROR_BUFFER_OVERFLOW
112……………………………………………………….
Нормальное выполнение:
C:\2011-spring\Лекции\Лекция2\Лаб2c>1
The computer name is EWGENIJ-PC
Упражнение:
Программно определить пути к системному каталогу
Windows и каталогу временных файлов Windows,
используя следующие функции Win32 API:
UINT GetWindowsDirectory( LPTSTR
lpBuffer, UINT uSize );
DWORD GetTempPath( DWORD
nBufferLength, LPSTR lpBuffer );
Замечание. Примеры венгерской нотации:
Префикс
Тип данных
u
беззнаковое целое
lp
sz
дальний указатель (long pointer) (атавизм)
строка, заканчивающаяся нулевым байтом (cстрока)
Создание процессов в Windows.
Замечание (использование семейств функций exec и
spawn в Windows-приложениях. ):
В заголовочном файле process.h содержаться макросы и
объявления функций exec*, spawn*, которые могут
использоваться для создания процессов. Стандарт
ANSI/ISO C не включает process.h, но этот заголовочный
файл и библиотеки времени исполнения, содержащие
реализации соответствующих функций присутстсвуют на
многих платформах.
В частности, эти функции поддерживаются компиляторами
компаний Borland и Microsoft на платформах MS DOS и
Windows 3.1.
В качестве расширения process.h содержится в стандарте
POSIX ( Portable Operating System Interface for Unix ).
Замечание: порты Cygwin и Interix
Примеры использования exec*:
#include <stdio.h>
#include <process.h>
void main(int argc, char* argv[]){
if(argc<2) return;
_execvp(argv[1],argv);
printf( "\nProcess was not execed." );
exit( 0 );
}
#include <stdio.h>
#include <process.h>
void main(){
char* argv[]={ "cmd", "/C", "dir", NULL };
_execvp(argv[0],argv);
printf( "\nProcess was not execed." );
exit( 0 );
}
void main(){
char* argv[]={ "notepad", NULL };
//_spawnvp(_P_OVERLAY, argv[0],argv);
_spawnvp(_P_NOWAIT, argv[0],argv);
printf( "\nParent process is yet running." );
exit( 0 );
}
winspawn.c
#include <windows.h>
#include <process.h>
int WINAPI WinMain( HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow){
char* argv[]={ "notepad", NULL };
//_spawnvp(_P_OVERLAY, argv[0],argv);
_spawnvp(_P_NOWAIT, argv[0],argv);
MessageBox(NULL, "Parent process is yet running.“,
"Message",MB_OK);
return 0;
}
#define WINAPI
__stdcall /*соглашение для вызова
функций Win32 API*/
LPSTR
HANDLE
HINSTANCE
typedef char *LPSTR
typedef PVOID HANDLE
typedef HANDLE HINSTANCE
hInstance – дескриптор текущего экземпляра приложения.
hPrevInstance – дескриптор предыдущего экземпляра
приложения (рудимент, всегда NULL).
lpCmdLine – параметры командной строки.
nCmdShow – константа, задающая вид окна.
Упражнение:
Модифицируйте программу winspawn.c так, чтобы процесс
создавался с задержкой в 5 секунд (или 5 часов).
Можно использовать функцию Win32 API:
VOID GetSystemTime( LPSYSTEMTIME lpSystemTime );
typedef struct _SYSTEMTIME {
WORD wYear; WORD wMonth;
WORD wDayOfWeek; WORD wDay;
WORD wHour; WORD wMinute;
WORD wSecond; WORD wMilliseconds;
} SYSTEMTIME, *LPSYSTEMTIME;
Download