|
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