Linux Exec rendszerhívás

Linux Exec System Call



A exec rendszerhívás egy olyan fájl végrehajtására szolgál, amely aktív folyamatban található. Ha az exec parancsot hívják, akkor az előző futtatható fájl lecserélődik, és új fájl kerül végrehajtásra.

Pontosabban azt mondhatjuk, hogy az exec rendszerhívás használata lecseréli a folyamatból származó régi fájlt vagy programot egy új fájlra vagy programra. A folyamat teljes tartalmát új program váltja fel.







Az exec () rendszerhívást végrehajtó felhasználói adatszegmens helyére az adatfájl kerül, amelynek nevét az argumentum tartalmazza az exec () hívása közben.



Az új program ugyanabba a folyamatterületbe kerül betöltésre. A jelenlegi folyamat csak új folyamattá változott, és ezért a folyamat azonosítója, a PID nem változik, ez azért van, mert nem új folyamatot hozunk létre, hanem csak egy folyamatot cserélünk le egy másik végrehajtási folyamattal.



Ha a jelenleg futó folyamat több szálat tartalmaz, akkor az összes szál megszakad, és az új folyamatkép betöltődik, majd végrehajtásra kerül. Nincsenek destruktor funkciók, amelyek lezárják az aktuális folyamat szálait.





A folyamat PID -je nem változik, de a folyamat adatai, kódja, verem, halom stb. Megváltoznak, és az újonnan betöltött folyamat adataival helyettesülnek. Az új folyamat a belépési ponttól indul.

Az Exec rendszerhívás funkciók gyűjteménye, és C programozási nyelven ezeknek a funkcióknak a standard nevei a következők:



  1. végrehajt
  2. execle
  3. execlp
  4. execv
  5. végrehajtani
  6. execvp


Itt meg kell jegyezni, hogy ezeknek a funkcióknak ugyanaz az alapja végrehajt amelyet egy vagy több betű követ. Ezeket az alábbiakban ismertetjük:

És: Ez egy mutatótömb, amely a környezeti változókra mutat, és kifejezetten átadásra kerül az újonnan betöltött folyamatnak.

az: l a parancssori argumentumok listát adtak át a függvénynek

p: p az elérési út környezeti változója, amely segít megtalálni a folyamatba betöltendő argumentumként átadott fájlt.

v: v a parancssori argumentumoké. Ezeket mutatók tömbjeként adják át a függvénynek.

Miért használják az exec programot?

Az exec akkor használatos, ha a felhasználó új fájlt vagy programot akar elindítani ugyanebben a folyamatban.

Végrehajtó belső munkája

Vegye figyelembe a következő pontokat, hogy megértse a végrehajtó működését:

  1. Az aktuális folyamatkép felülírásra kerül egy új folyamatképpel.
  2. Az új folyamatkép az, amelyet végrehajtási argumentumként adtál meg
  3. A jelenleg futó folyamat véget ért
  4. Az új folyamatkép ugyanazzal a folyamatazonosítóval, ugyanazzal a környezettel és ugyanazzal a fájlleíróval rendelkezik (mivel a folyamat nincs lecserélve.
  5. Ez befolyásolja a CPU statisztikáját és a virtuális memóriát. Az aktuális folyamatkép virtuális memórialeképezését az új folyamatkép virtuális memóriája váltja fel.

A végrehajtó családi függvények szintaxisa:

Az alábbiakban a végrehajtás minden függvényének szintaxisa látható:

int execl (const char* elérési út, const char* arg,…)
int execlp (const char* fájl, const char* arg,…)
int execle (const char* elérési út, const char* arg,…, char* const envp [])
int execv (const char* elérési út, const char* argv [])
int execvp (const char* fájl, const char* argv [])
int execvpe (const char* fájl, const char* argv [], char* const envp [])

Leírás:

E függvények visszatérési típusa az Int. Ha a folyamatkép sikeresen le lett cserélve, semmi sem kerül vissza a hívó funkcióhoz, mert az azt hívó folyamat már nem fut. De ha bármilyen hiba van, a -1 visszaadódik. Ha bármilyen hiba történt, a errno van beállítva.

A szintaxisban:

  1. pálya a végrehajtandó fájl teljes elérési útnevének megadására szolgál.
  1. mérges átment -e az érvelés. Valójában ez a fájl neve, amelyet a folyamat végrehajt. A legtöbb esetben az arg és a path értéke azonos.
  1. const char* arg a execl (), execlp () és execle () függvényekben arg0, arg1, arg2,…, argn. Ez alapvetően a null befejezett karakterláncokra mutató mutatók listája. Itt az első argumentum a fájlnévre mutat, amelyet a 2. pontban leírtak szerint hajtunk végre.
  1. envp egy tömb, amely olyan mutatókat tartalmaz, amelyek a környezeti változókra mutatnak.
  1. fájlt az útvonalnév megadására szolgál, amely azonosítja az új folyamatképfájl elérési útját.
  1. Az exec függvényei azzal végződnek És az új folyamatkép környezetének megváltoztatására szolgálnak. Ezek a függvények az argumentum használatával megfelelnek a környezeti beállítások listájának envp . Ez az argumentum karakterek tömbje, amely null végű karakterláncra mutat, és meghatározza a környezeti változót.

A exec családi funkciók használatához a következő fejlécfájlt kell tartalmaznia a C programjában:

#befoglalni

Példa 1: Exec rendszerhívás használata C programban

Tekintsük a következő példát, amelyben az exec rendszerhívást használtuk a C programozásban Linux, Ubuntu esetén: Két c fájlunk van itt: example.c és hello.c:

példa.c

KÓD:

#befoglalni
#befoglalni
#befoglalni
intfő-(intargc, char *argv[])
{
printf ('A példa PID -je. C = %d n',hülye());
char *args[] = {'Helló', 'C', 'Programozás',NULLA};
execv('./Helló',args);
printf ('Vissza a példához.c');
Visszatérés 0;
}

szia.c

KÓD:

#befoglalni
#befoglalni
#befoglalni
intfő-(intargc, char *argv[])
{
printf ('Hello.c -ben vagyunk n');
printf ('PID a hello.c = %d n',hülye());
Visszatérés 0;
}

KIMENET:

A példa PID -je. C = 4733
Hello.c -ben vagyunk
Hello PID. C = 4733

A fenti példában van egy example.c fájl és a hello.c fájl. A példa .c fájlban először kinyomtattuk az aktuális folyamat azonosítóját (a example.c fájl az aktuális folyamatban fut). Ezután a következő sorban létrehoztunk egy karaktermutató tömböt. Ennek a tömbnek az utolsó eleme legyen NULL, mint végpont.

Ezután az execv () függvényt használtuk, amely a fájlnevet és a karaktermutató tömböt veszi argumentumként. Itt meg kell jegyezni, hogy a ./ fájlt használtuk a fájl nevével, ez határozza meg a fájl elérési útját. Mivel a fájl abban a mappában van, ahol az example.c található, nincs szükség a teljes elérési út megadására.

Az execv () függvény meghívásakor a folyamatképünk most lecserélődik. A example.c fájl nincs folyamatban, de a hello.c fájl van folyamatban. Látható, hogy a folyamat azonosítója ugyanaz, függetlenül attól, hogy a hello.c folyamatkép vagy példa. C folyamatkép, mivel a folyamat ugyanaz, és a folyamatkép csak le van cserélve.

Itt még egy dolgot kell megjegyeznünk, amely a printf () utasítás, miután a execv () nem hajtódik végre. Ennek az az oka, hogy a vezérlés soha nem tér vissza a régi folyamatképhez, miután az új folyamatkép felváltja azt. A vezérlés csak akkor tér vissza a hívás funkcióhoz, ha a folyamatkép cseréje sikertelen. (A visszatérési érték ebben az esetben -1).

Különbség a fork () és az exec () rendszerhívások között:

A fork () rendszerhívás egy futó folyamat pontos másolatának létrehozására szolgál, a létrehozott példány pedig a gyermekfolyamat, a futó folyamat pedig a szülői folyamat. Míg az exec () rendszerhívást arra használják, hogy egy folyamatképet új folyamatképpel helyettesítsenek. Ezért az exec () rendszerhívásban nincs fogalma a szülői és gyermeki folyamatoknak.

A fork () rendszerhívásban a szülői és utódfolyamatok egyszerre kerülnek végrehajtásra. De a exec () rendszerhívásban, ha a folyamatkép cseréje sikeres, a vezérlő nem tér vissza oda, ahol az exec függvényt hívták, hanem az új folyamatot hajtja végre. A vezérlés csak akkor kerül vissza, ha hiba történt.

2. példa: A fork () és az exec () rendszerhívások kombinálása

Tekintsük a következő példát, amelyben a fork () és az exec () rendszerhívásokat is használtuk ugyanabban a programban:

példa.c

KÓD:

#befoglalni
#befoglalni
#befoglalni
intfő-(intargc, char *argv[])
{
printf ('A példa PID -je. C = %d n',hülye());
pid_t p;
o=Villa();
ha(o== -1)
{
printf ('Hiba történt a (()) hívás közben);
}
ha(o==0)
{
printf ('A gyermek folyamatban vagyunk n');
printf (- A hello.c hívása gyermekfolyamatból n');
char *args[] = {'Helló', 'C', 'Programozás',NULLA};
execv('./Helló',args);
}
más
{
printf („A szülői folyamatban vagyunk”);
}
Visszatérés 0;
}

hello.c:

KÓD:

#befoglalni
#befoglalni
#befoglalni
intfő-(intargc, char *argv[])
{
printf ('Hello.c -ben vagyunk n');
printf ('PID a hello.c = %d n',hülye());
Visszatérés 0;
}

KIMENET:

A példa PID -je. C = 4790
Szülői folyamatban vagyunk
Gyermek folyamatban vagyunk
A hello.c hívása gyermekfolyamatból
Sziasztok vagyunk.c
Hello PID. C = 4791

Ebben a példában a fork () rendszerhívást használtuk. Amikor a gyermekfolyamat létrejön, 0 lesz rendelve a p -hez, majd áttérünk a gyermekfolyamatra. Most az if (p == 0) utasításokat tartalmazó blokk kerül végrehajtásra. Megjelenik egy üzenet, és az execv () rendszerhívást használtuk, és az aktuális gyermek folyamatképet, amely a example.c helyére a hello.c lesz. A execv () hívás előtt a gyermek és a szülő folyamat ugyanaz volt.

Látható, hogy a example.c és a hello.c PID -je most más. Ez azért van, mert a example.c a szülői folyamatkép és a hello.c a gyermekfolyamatkép.