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.

Programovací jazyk C:

#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;
}

COBOL:

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);
?>

Python:

#!/usr/bin/python
import sys
sys.exit(0)

Unix shell:

$ exit 0

Pascal:

program pr1;
begin
 exit();
end.

DOS Assembler:

; 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