exit (systémové volání)
exit() je v informatice speciální systémové volání jádra operačního systému, pomocí kterého proces ukončí svoji činnost. Ukončením procesu jsou operačnímu systému vráceny všechny prostředky, které proces alokoval (operační paměť, otevřené soubory atd.). V případě multithreadingu je ukončeno jen příslušné vlákno.
Popis funkce
V unixových systémech vznikají procesy tak, že rodičovský proces zavolá systémové volání fork()
, čímž vznikne potomek. Rodič může poté využít systémové volání wait()
, pomocí kterého čeká na ukončení potomka a zároveň vyzvedne návratový kód. Potomek může být ukončen různými způsoby: standardně zde uvedeným voláním exit()
, nestandardně pak na základě nějaké chyby nebo přijetí signálu (např. SIGTERM, SIGINT, SIGKILL), kdy je rodičovi zaslán signál SIGCHLD.
Většina operačních systémů umožňuje předat rodičovskému procesu návratový kód v podobě malého celého čísla; operační systém Plan 9 umožňuje pro upřesnění předat textový řetězec.
Zakončovací operace
Volání exit()
obvykle před vlastním zavoláním systémového volání operačního systému provádí úklidové operace v prostoru procesu. Některé programovací jazyky umožňují na ukončení programu navázat podprogramy, které jsou vyvolány těsně před ukončením programu. Teprve po jejich dokončení je proces definitivně ukončen a jím používané prostředky předány zpět operačnímu systému.
Některé jazyky poskytují možnost vynechat zakončovací úklidové operace. Například v jazyce C99 je to funkce _exit()
, která se používá spolu s voláními fork-exec-exit, kdy by potomek mohl nesprávně uvolnit prostředky patřící rodiči.
Sirotci a Zombie
V některých operačních systémech je správa potomků, jimž se předčasně ukončil rodič řešena speciálním způsobem.
V unixových systémech je rodič povinen vyzvednout návratový kód potomka. Pokud je rodič potomka ukončen dříve než potomek, je jádrem operačního systému nastaven jako rodič proces číslo 1 (typicky init), který návratové kódy po ukončení potomka vyzvedává a obratem je zahazuje. V případě, že potomek skončí a rodič návratový kód nevyzvedne, vznikne z potomka tak zvaný „zombie“ proces. Zombie již jako proces neexistuje, avšak v tabulce procesů (PCB) jsou nadále udržovány základní informace o procesu včetně jeho návratového kódu. Zombie procesy nelze z tabulky procesů odstranit jinak, než že rodič vyzvedne jejich návratový kód. Pokud je rodič špatně naprogramován, může ho správce systému (root) násilně ukončit. Zombie procesy budou „adoptovány“ procesem číslo 1, který je typicky naprogramován tak, aby návratové kódy vyzvedl (viz výše).
Příklady
Následující programy se ukončují a předávají přes jádro operačního systému návratový kód rodiči.
#include <stdlib.h>
int main(void)
{
exit(EXIT_SUCCESS);
}
nebo:
#include <stdlib.h>
int main(void)
{
return EXIT_SUCCESS;
}
C++:
#include <cstdlib>
int main(void)
{
std::exit(EXIT_SUCCESS);
}
nebo:
#include <cstdlib>
int main(void)
{
return EXIT_SUCCESS;
}
IDENTIFICATION DIVISION.
PROGRAM-ID. SUCCESS-PROGRAM.
PROCEDURE DIVISION.
MAIN.
MOVE ZERO TO RETURN-CODE.
END PROGRAM.
Java:
public class Success
{
public static void main(String[] args)
{
System.exit(0);
}
}
DOS Batch file:
set ERRORLEVEL=0
exit
Perl:
#!/bin/perl
exit;
PHP:
<?php
exit(0);
?>
#!/usr/bin/python
import sys
sys.exit(0)
$ exit 0
program pr1;
begin
exit();
end.
; For MASM/TASM
.MODEL SMALL
.STACK
.CODE
main PROC NEAR
MOV AH, 4Ch ; Service 4Ch - Terminate with Error Code
MOV AL, 0 ; Error code
INT 21h ; Interrupt 21h - DOS General Interrupts
main ENDP
END main ; Starts at main
Někteří programátoři používají pro naplnění AH i AL jednu instrukci:
MOV AX, 4C00h ; nahradit 00 požadovaným chybovým kódem
Linux Assembler:
; For NASM MOV AL, 1 ; Funkce 1: exit() MOV EBX, 0 ; Návratový kód INT 80h ; Jediné volání přerušení, které Linux používá!
Související články
Externí odkazy
- http://opengroup.org/onlinepubs/009695399/functions/exit.html – popis systémového volání exit() (anglicky)