310 likes | 414 Views
Процессы. Процесс – это исполняемый экземпляр программы и набор ресурсов, которые выделяются данной исполняемой программе. Ресурсы: виртуальное адресное пространство; системные ресурсы –области физической памяти, процессорное время, файлы, растровые изображения и т.д.;
E N D
Процессы Процесс – это исполняемый экземпляр программы и набор ресурсов, которые выделяются данной исполняемой программе. • Ресурсы: • виртуальное адресное пространство; • системные ресурсы –области физической памяти, процессорное время, файлы, растровые изображения и т.д.; • модули процесса, то есть исполняемые модули, загруженные (отображенные) в его адресное пространство – основной загрузочный модуль, библиотеки динамической компоновки, драйверы устройств и т.д.; • уникальный идентификационный номер, называемый идентификатором процесса; • потоки (по крайней мере, один поток).
Модель процесса: Переключение процессора Квант времени Поток A Переключение процессора Квант времени Поток B Квант времени ………… t Планировщик процессов. Диспетчер процессов • Сохранение контекста текущего потока, регистров, стека и областей памяти. • Определение очередного потока. • Восстановление контекста очередного потока.
Последовательность исполнения потоков в среде с вытесняющей многозадачностью: В системе определен квант времени (порядка десятков миллисекунд) – процессорное время выделяемое одному потоку (каждому - своё). Длительность выполнения одного потока не может превышать одного кванта. Когда это время заканчивается, диспетчерпроцессовпереключает процессор на выполнение другого потока. При этом состояние регистров, стека и областей памяти – контекст потока, сохраняется в стеке потока. Очередность потоков определяется их состоянием и приоритетом.
Действие 1 3 2 Блокировка Готовность 4 Состояние процессов: • Процесс заблокирован в ожидании ввода. • Диспетчер выбирает другой процесс. • Диспетчер выбирает данный процесс. • Входные данные стали доступны.
Реализацией процессов является таблица процессов, - линейный список (программно реализованный, как массив структур). Информация о процессах хранится в таблице процессов и обновляется планировщиком процессов.
Некоторые поля типичной записи таблицы процессов: Корневой каталог Рабочий каталог Дескрипторы файлов Идентификатор пользователя Регистры Счетчик команд Указатель стека Состояние процесса Приоритет Идентификатор процесса Родительский процесс Время запуска процессора Использованное время процессора
Создание процесса: #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()); }
С точки зрения планировщика дочерний и родительский процессы независимы:
#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:
Чтобы обеспечить поддержку типов Microsoft Windows в программе, необходимо включить в нее заголовочный файл windows.h. Этот файл также содержит объявления функций интерфейса системных вызовов MS WindowsWin32 API. Примеробъявления функции: BOOL GetComputerName( LPTSTR lpBuffer; LPDWORD nSize; );
#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….……………………………………………………111 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); Замечание. Примеры венгерской нотации:
Создание процессов в 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 yetrunning.“,"Message",MB_OK); return 0; }
#define WINAPI __stdcall /*соглашение для вызова функций Win32 API*/ 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;