Linux Exec системно обаждане

Linux Exec System Call



Системното обаждане exec се използва за изпълнение на файл, който се намира в активен процес. Когато се извика exec, предишният изпълним файл се заменя и се изпълнява нов файл.

По -точно можем да кажем, че използването на exec системно обаждане ще замени стария файл или програма от процеса с нов файл или програма. Цялото съдържание на процеса се заменя с нова програма.







Сегментът от потребителски данни, който изпълнява системното извикване exec (), се заменя с файла с данни, чието име е предоставено в аргумента, докато се извиква exec ().



Новата програма се зарежда в същото пространство на процеса. Текущият процес просто се превръща в нов процес и следователно PID на процеса не се променя, това е така, защото не създаваме нов процес, а просто заменяме процес с друг процес в exec.



Ако текущият процес съдържа повече от една нишка, тогава всички нишки ще бъдат прекратени и новото изображение на процеса ще бъде заредено и след това изпълнено. Няма функции на деструктор, които да прекратяват нишките на текущия процес.





PID на процеса не се променя, но данните, кодът, стекът, купчината и т.н. на процеса се променят и се заменят с тези на новозареден процес. Новият процес се изпълнява от входната точка.

Системното извикване на Exec е колекция от функции и в езика за програмиране на C стандартните имена за тези функции са както следва:



  1. execl
  2. екзекъл
  3. execlp
  4. execv
  5. execve
  6. execvp


Тук трябва да се отбележи, че тези функции имат една и съща база exec последвано от една или повече букви. Те са обяснени по -долу:

И: Това е масив от указатели, който сочи към променливите на средата и се предава изрично на новозаредения процес.

на: l е за аргументите на командния ред, предаващи списък на функцията

p: p е променливата на средата на пътя, която помага да се намери файлът, предаден като аргумент, който да бъде зареден в процеса.

v: v е за аргументите на командния ред. Те се предават като масив от указатели към функцията.

Защо се използва exec?

exec се използва, когато потребителят иска да стартира нов файл или програма в същия процес.

Вътрешна работа на exec

Помислете за следните точки, за да разберете работата на exec:

  1. Текущото изображение на процеса се презаписва с ново изображение на процеса.
  2. Новият образ на процеса е този, който сте предали като exec аргумент
  3. Текущият процес е приключил
  4. Новият образ на процеса има същия идентификатор на процеса, същата среда и същия дескриптор на файла (тъй като процесът не се заменя, изображението на процеса се заменя)
  5. Статутът на процесора и виртуалната памет са засегнати. Картографирането на виртуалната памет на текущото изображение на процеса се заменя с виртуална памет на ново изображение на процеса.

Синтаксиси на exec семейни функции:

Следните са синтаксисите за всяка функция на exec:

int execl (const char* пътека, const char* arg, ...)
int execlp (const char* файл, const char* arg, ...)
int execle (const char* път, const char* arg,…, char* const envp [])
int execv (const char* път, const char* argv [])
int execvp (const char* файл, const char* argv [])
int execvpe (const char* файл, const char* argv [], char* const envp [])

Описание:

Типът на връщане на тези функции е Int. Когато образът на процеса е успешно заменен, нищо не се връща към извикващата функция, тъй като процесът, който го е извикал, вече не работи. Но ако има някаква грешка -1 ще бъде върната. Ако възникне някаква грешка an ерно е зададен.

В синтаксиса:

  1. път се използва за определяне на пълното име на пътя на файла, който трябва да се изпълни.
  1. ядосан е приет аргументът. Всъщност това е името на файла, който ще бъде изпълнен в процеса. В повечето случаи стойността на arg и path е еднаква.
  1. const char* arg във функциите execl (), execlp () и execle () се разглеждат като arg0, arg1, arg2,…, argn. По същество това е списък с указатели към нулиращи низове. Тук първият аргумент сочи името на файла, което ще бъде изпълнено, както е описано в точка 2.
  1. envp е масив, който съдържа указатели, които сочат към променливите на средата.
  1. файл се използва за задаване на името на пътя, който ще идентифицира пътя на новия файл с изображение на процеса.
  1. Функциите на exec извикват, че завършват с И се използват за промяна на средата за новия образ на процеса. Тези функции преминават списък на настройките на средата с помощта на аргумента envp . Този аргумент е масив от знаци, който сочи към нулиран завършен String и определя променлива на средата.

За да използвате функциите на семейството exec, трябва да включите следния заглавен файл във вашата C програма:

#включва

Пример 1: Използване на exec системно обаждане в C програма

Помислете за следния пример, в който сме използвали exec системно обаждане при програмиране на C в Linux, Ubuntu: Тук имаме два c файла example.c и hello.c:

пример.в

КОД:

#включва
#включва
#включва
intглавен(intargc, char *argv[])
{
printf ('PID на пример. C = %dн',избухвам());
char *аргументи[] = {'Здравейте', '° С', 'Програмиране',НУЛА};
execv('./Здравейте',аргументи);
printf ('Назад към example.c');
връщане 0;
}

здравей.c

КОД:

#включва
#включва
#включва
intглавен(intargc, char *argv[])
{
printf („Ние сме в Hello.cн');
printf ('PID на hello.c = %dн',избухвам());
връщане 0;
}

ИЗХОД:

PID от пример.c = 4733
Ние сме в Hello.c
PID на hello.c = 4733

В горния пример имаме example.c файл и hello.c файл. В примерния .c файл първо сме отпечатали ID на текущия процес (файл example.c работи в текущия процес). След това в следващия ред създадохме масив от указатели на символи. Последният елемент от този масив трябва да бъде NULL като крайна точка.

След това използвахме функцията execv (), която приема името на файла и масива на показалеца като символ. Тук трябва да се отбележи, че сме използвали ./ с името на файла, той посочва пътя на файла. Тъй като файлът е в папката, където се намира example.c, няма нужда да посочвате пълния път.

Когато функцията execv () бъде извикана, образът на процеса ни ще бъде заменен сега файлът example.c не е в процеса, но файлът hello.c е в процес. Може да се види, че идентификаторът на процеса е един и същ, независимо дали hello.c е изображение на процес или example.c е изображение на процес, защото процесът е същият и изображението на процеса се заменя само.

След това трябва да отбележим още нещо, което е инструкцията printf (), след като execv () не се изпълнява. Това е така, защото контролът никога не се връща към старото изображение на процеса, след като новото изображение на процеса го замени. Контролът се връща към извикващата функция само когато подмяната на образа на процеса е неуспешна. (В този случай връщаната стойност е -1).

Разлика между системните извиквания fork () и exec ():

Системното извикване fork () се използва за създаване на точно копие на изпълняващ се процес и създаденото копие е дъщерния процес, а изпълняващият процес е родителския процес. Като има предвид, че системното извикване exec () се използва за замяна на образ на процес с нов образ на процес. Следователно няма концепция за родителски и дъщерни процеси в системния извикване на exec ().

В системното извикване fork () родителските и дъщерните процеси се изпълняват едновременно. Но в системното извикване на exec (), ако подмяната на образа на процеса е успешна, контролата не се връща там, където е била извикана функцията exec, а ще изпълни новия процес. Контролът ще бъде прехвърлен обратно само ако има грешка.

Пример 2: Комбиниране на системни извиквания fork () и exec ()

Помислете за следния пример, в който сме използвали системни извиквания fork () и exec () в една и съща програма:

пример.в

КОД:

#включва
#включва
#включва
intглавен(intargc, char *argv[])
{
printf ('PID на пример. C = %dн',избухвам());
pid_t p;
стр=вилица();
ако(стр== -1)
{
printf ('Има грешка при извикване на fork ()');
}
ако(стр==0)
{
printf („Ние сме в детския процесн');
printf („Извикване на hello.c от дъщерния процесн');
char *аргументи[] = {'Здравейте', '° С', 'Програмиране',НУЛА};
execv('./Здравейте',аргументи);
}
иначе
{
printf („Ние сме в родителския процес“);
}
връщане 0;
}

здравей.c:

КОД:

#включва
#включва
#включва
intглавен(intargc, char *argv[])
{
printf („Ние сме в Hello.cн');
printf ('PID на hello.c = %dн',избухвам());
връщане 0;
}

ИЗХОД:

PID от пример.c = 4790
Ние сме в родителски процес
Ние сме в детски процес
Извикване на hello.c от дъщерния процес
Ние сме в hello.c
PID на hello.c = 4791

В този пример използвахме fork () системно извикване. Когато се създаде дъщерния процес, 0 ще бъде присвоено на р и след това ще преминем към дъщерния процес. Сега блокът от изявления с if (p == 0) ще бъде изпълнен. Показва се съобщение и ние използвахме системно обаждане execv () и текущото изображение на дъщерния процес, което е example.c, ще бъде заменено с hello.c. Преди execv () извикването на дъщерни и родителски процеси беше същото.

Може да се види, че PID на example.c и hello.c е различен сега. Това е така, защото example.c е изображението на родителския процес и hello.c е изображението на дъщерния процес.