|
2466 | 2466 | %%%%% |
2467 | 2467 |
|
2468 | 2468 | \begin{slide} |
2469 | | -\sltitle{Systémová volání, funkce} |
| 2469 | +\sltitle{System calls, functions} |
2470 | 2470 | \begin{itemize} |
2471 | | -\item v UNIXu se rozli¹ují \emsl{systémová volání} a \emsl{knihovní |
2472 | | -funkce}. Toto rozli¹ení dodr¾ují i manuálové stránky: sekce |
2473 | | -\emsl{2} obsahuje systémová volání (\emph{syscalls}), sekce \emsl{3} |
2474 | | -knihovní funkce (\emph{library functions}). |
| 2471 | +\item In UNIX a distinction is made of \emsl{system calls} and \emsl{library |
| 2472 | +functions}. This division is maintained in man pages: section \emsl{2} contains |
| 2473 | +system call man pages and section \emsl{3} library functions. |
2475 | 2474 | \begin{itemize} |
2476 | | - \item knihovní funkce se vykonávají v u¾ivatelském re¾imu, |
2477 | | - stejnì jako ostatní kód programu. |
2478 | | - \item systémová volání mají také tvar volání funkce. Pøíslu¹ná funkce ale |
2479 | | - pouze zpracuje argumenty volání a pøedá øízení jádru pomocí instrukce |
2480 | | - synchronního pøeru¹ení. Po návratu z jádra funkce upraví výsledek a pøedá ho |
2481 | | - volajícímu. |
| 2475 | + \item library functions are executed in user mode, just like the rest |
| 2476 | + of the program's code. |
| 2477 | + \item system calls also have the form of a function. However given function |
| 2478 | + only processes arguments and passes the control to the kernel using |
| 2479 | + synchronous interrupt instruction. Once it returns from the kernel, |
| 2480 | + it will adjust the result and returns it to the caller. |
2482 | 2481 | \end{itemize} |
2483 | | -\item standardy tyto kategorie nerozli¹ují -- z hlediska programátora je jedno, |
2484 | | -zda urèitou funkci provede jádro nebo knihovna. |
| 2482 | +\item this distinction is not made in the standard -- from programmer's |
| 2483 | +perspective it does not \emph{usually} matter if given function is processed |
| 2484 | +by a library or kernel. |
2485 | 2485 | \end{itemize} |
2486 | 2486 | \end{slide} |
2487 | 2487 |
|
2488 | 2488 | \begin{itemize} |
2489 | | -\item zjednodu¹enì lze øíci, ¾e systémové volání je funkce, která |
2490 | | -jen upraví své argumenty do vhodné podoby, pøepne re¾im procesoru a |
2491 | | -skuteènou práci nechá na jádru. Nakonec zase upraví výsledek. |
2492 | | -\emsl{Knihovní funkce mù¾e a nemusí volat jádro, ale v¾dy sama dìlá |
2493 | | -nìjakou netriviální èinnost v u¾ivatelském re¾imu.} |
2494 | | -\item v assembleru je mo¾né zavolat volání jádra pøímo |
2495 | | -\item API jádra je definované na úrovni volání funkcí standardní |
2496 | | -knihovny, nikoliv na úrovni pøeru¹ení a datových struktur |
2497 | | -pou¾ívaných tìmito funkcemi pro pøedání øízení jádru. Mechanismus |
2498 | | -pøepnutí mezi u¾ivatelským re¾imem a re¾imem jádra se toti¾ mù¾e |
2499 | | -li¹it nejen v závislosti na hardwarové platformì, ale i mezi rùznými |
2500 | | -verzemi systému na stejném hardwaru. |
| 2489 | +\item The transition from userland to kernel can be costly; if the program |
| 2490 | +executes lot of syscalls, it can have a negative effect on its performance. |
| 2491 | +\emsl{Library function can but does not have to perform some system calls, |
| 2492 | +however it always does some non-trivial work in user mode.} |
| 2493 | +\item It is possible to perform system call directly in assembler. |
| 2494 | +\item The kernel API is defined w.r.t. function calls of the standard library, |
| 2495 | +not w.r.t. interrupt level and data structures used by these functions when |
| 2496 | +passing control to the kernel. The mechanism of switching between user and |
| 2497 | +kernel mode can differ not only depending on hardware platform but also between |
| 2498 | +different versions of the same system on the same hardware. |
2501 | 2499 | \end{itemize} |
| 2500 | + |
2502 | 2501 | %%%%% |
2503 | 2502 |
|
2504 | 2503 | \pdfbookmark[1]{syscall return values semantics}{syscallretvals} |
2505 | 2504 |
|
2506 | 2505 | \begin{slide} |
2507 | | -\sltitle{Návratové hodnoty systémových volání} |
| 2506 | +\sltitle{System call return values} |
2508 | 2507 | \setlength{\baselineskip}{0.8\baselineskip} |
2509 | 2508 | \begin{itemize} |
2510 | | -\item celoèíselná návratová hodnota (\texttt{int}, \texttt{pid\_t}, |
2511 | | -\texttt{off\_t}, apod.) |
| 2509 | +\item integer return value (\texttt{int}, \texttt{pid\_t}, |
| 2510 | +\texttt{off\_t}, etc.) |
2512 | 2511 | \begin{itemize} |
2513 | | - \item \texttt{>= 0} \dots{} operace úspì¹nì provedena |
2514 | | - \item \texttt{== -1} \dots{} chyba |
| 2512 | + \item \texttt{>= 0} \dots{} success |
| 2513 | + \item \texttt{== -1} \dots{} failure |
2515 | 2514 | \end{itemize} |
2516 | | -\item návratová hodnota typu ukazatel |
| 2515 | +\item pointer return value |
2517 | 2516 | \begin{itemize} |
2518 | | - \item \texttt{!= NULL} \dots{} operace úspì¹nì provedena |
2519 | | - \item \texttt{== NULL} \dots{} chyba |
| 2517 | + \item \texttt{!= NULL} \dots{} success |
| 2518 | + \item \texttt{== NULL} \dots{} failure |
2520 | 2519 | \end{itemize} |
2521 | | -\item po neúspì¹ném systémovém volání je kód chyby v globální |
2522 | | -promìnné \texttt{extern int \funnm{errno};} |
2523 | | -\item úspì¹né volání nemìní hodnotu v \texttt{errno}! Je tedy tøeba |
2524 | | -nejprve otestovat návratovou hodnotu a pak teprve \texttt{errno}. |
2525 | | -\item chybové hlá¹ení podle hodnoty v \texttt{errno} vypí¹e funkce\\ |
| 2520 | +\item after failed syscall the error code is stored in global variable |
| 2521 | +\texttt{extern int \funnm{errno};} |
| 2522 | +\item successful syscall never changes \texttt{errno} ! It is therefore |
| 2523 | +necessary to test the return value first and then check \texttt{errno}. |
| 2524 | +\item error message depending on the \texttt{errno} value can be printed with\\ |
2526 | 2525 | \texttt{void \funnm{perror}(const char *\emph{s});} |
2527 | | -\item textový popis chyby s daným èíslem vrátí funkce\\ |
| 2526 | +\item textual representation for given value is returned by\\ |
2528 | 2527 | \texttt{char *\funnm{strerror}(int \emph{errnum});} |
2529 | 2528 | \end{itemize} |
2530 | 2529 | \end{slide} |
2531 | 2530 |
|
2532 | 2531 | %%%%% |
2533 | 2532 |
|
2534 | 2533 | \begin{itemize} |
2535 | | -\item \label{ERRNO} v Solarisu je hodnota \texttt{errno} ve |
2536 | | -skuteènosti knihovnou \texttt{libc} definovaná jako dereferencovaný |
2537 | | -pointer na integer (specifický pro daný userland thread) a hodnota se |
2538 | | -nastavuje ihned po výstupu z instrukce pro systémové volání. Napø. na i386 |
2539 | | -architektuøe je hodnota \texttt{errno} po návratu z kernelu (po dokonèení |
2540 | | -instrukce \texttt{sysenter}) ulo¾ena v registru \texttt{eax} (pøed voláním |
2541 | | -v ní bylo èíslo syscallu). Je to tedy knihovna \texttt{libc} kdo je |
2542 | | -zodpovìdný za to, ¾e program uvidí správnou hodnotu \texttt{errno}. |
2543 | | - |
2544 | | - |
2545 | | -\item funkce pro práci s vlákny \texttt{pthread\_*} nenastavují |
2546 | | -\texttt{errno}, ale vrací buï nulu (úspìch) nebo pøímo kód chyby. |
2547 | | -\item pro nìkterá volání mù¾e mít smysl i návratová hodnota |
2548 | | -\texttt{-1}. Pak je tøeba nejprve nastavit \texttt{errno~=~0} a po |
2549 | | -návratu zkontrolovat, zda se \texttt{errno} zmìnilo. Napø. funkce |
2550 | | -\texttt{strtol} vrací pøi chybì 0, co¾ je platná hodnota i pro |
2551 | | -správný výsledek (a $-1$ je samozøejmì platný výsledek také). |
2552 | | -\item je tedy v¾dy nutné si pøeèíst manuálovou stránku pro pøí¹lu¹né |
2553 | | -volání nebo knihovní funkci |
2554 | | -\item pozn.: úspì¹nost funkcí ze \texttt{stdio.h} je tøeba testovat pomocí\\ |
2555 | | -\texttt{int \funnm{ferror}(FILE *\emph{stream})}, proto¾e jinak nelze rozli¹it |
2556 | | -mezi chybou a koncem streamu. Vzhledem k tomu, ¾e tyto funkce nepou¾íváme (kromì |
2557 | | -\texttt{printf} a \texttt{fprintf} na \texttt{stdout}, resp. \texttt{stderr}), |
2558 | | -nemìli byste ji potøebovat. |
| 2534 | +\item \label{ERRNO} In Solaris \texttt{errno} is in reality defined in |
| 2535 | +\texttt{libc} as a dereferenced pointer to integer (specific to userland thread) |
| 2536 | +and the value is set right after the instruction for system call. |
| 2537 | +For example on i386 architecture the \texttt{errno} value is stored in the |
| 2538 | +\texttt{eax} register after the return from the syscall (after the |
| 2539 | +\texttt{sysenter} instruction is executed). Before the instruction the register |
| 2540 | +held the system call number. It is therefore the \texttt{libc} library that is |
| 2541 | +responsible for the program to see the correct \texttt{errno} value. |
| 2542 | +\item The POSIX thread functions (\texttt{pthread\_*}) do not set |
| 2543 | +\texttt{errno}, rather they return either zero or error code. |
| 2544 | +\item For some calls it the \texttt{-1} is semantically valid. To use such |
| 2545 | +functions, it is necessary to set \texttt{errno~=~0} before the call and check |
| 2546 | +whether the value changed after the call. E.g. the \texttt{strtol} function |
| 2547 | +returns 0 on failure, which is valid value even for valid result |
| 2548 | +(and $-1$ is also valid result value). |
| 2549 | +\item It is therefore necessary to always read the man page for appropriate |
| 2550 | +system call or library function. |
| 2551 | +\item Note that the failure or functions from \texttt{stdio.h} it is necessary |
| 2552 | +to test using\\ |
| 2553 | +\texttt{int \funnm{ferror}(FILE *\emph{stream})}, because it is not otherwise |
| 2554 | +possible to distinguish between an error and end of stream. Considering we are |
| 2555 | +not using these functions in the lecture (except |
| 2556 | +\texttt{printf} and \texttt{fprintf} for \texttt{stdout}, resp. |
| 2557 | +\texttt{stderr}), you should not need it. |
2559 | 2558 | \end{itemize} |
2560 | 2559 |
|
2561 | 2560 | \begin{slide} |
|
0 commit comments