From 0a2e3728567f39f6b60cbb4a1a9dfd8bcba13481 Mon Sep 17 00:00:00 2001 From: Seema Shivaram Upadhya Date: Wed, 11 Aug 2021 20:50:58 -0700 Subject: [PATCH] System calls and signals (#120) * System calls and signals * Changing the url for Linux basics Co-authored-by: Seema Shivaram Upadhya --- courses/index.md | 1 + .../system_calls_and_signals/conclusion.md | 18 ++ ...ransition_between_User_and_Kernel_Mode.png | Bin 0 -> 33642 bytes .../system_calls_and_signals/intro.md | 29 +++ .../system_calls_and_signals/signals.md | 137 +++++++++++++ .../system_calls_and_signals/system_calls.md | 194 ++++++++++++++++++ mkdocs.yml | 5 + 7 files changed, 384 insertions(+) create mode 100644 courses/level102/system_calls_and_signals/conclusion.md create mode 100755 courses/level102/system_calls_and_signals/images/Transition_between_User_and_Kernel_Mode.png create mode 100644 courses/level102/system_calls_and_signals/intro.md create mode 100644 courses/level102/system_calls_and_signals/signals.md create mode 100644 courses/level102/system_calls_and_signals/system_calls.md diff --git a/courses/index.md b/courses/index.md index 147dfa1..0178374 100644 --- a/courses/index.md +++ b/courses/index.md @@ -30,6 +30,7 @@ In this course, we are focusing on building strong foundational skills. The cour - Level 102 - Linux Advanced - [Containers and orchestration](https://linkedin.github.io/school-of-sre/level102/containerization_and_orchestration/intro/) + - [System Calls and Signals](https://linkedin.github.io/school-of-sre/level102/system_calls_and_signals/intro/) - [Networking](https://linkedin.github.io/school-of-sre/level102/networking/introduction/) - [System Design](https://linkedin.github.io/school-of-sre/level102/system_design/intro/) - [System troubleshooting and performance improvements](https://linkedin.github.io/school-of-sre/level102/system_troubleshooting_and_performance/introduction/) diff --git a/courses/level102/system_calls_and_signals/conclusion.md b/courses/level102/system_calls_and_signals/conclusion.md new file mode 100644 index 0000000..fa46483 --- /dev/null +++ b/courses/level102/system_calls_and_signals/conclusion.md @@ -0,0 +1,18 @@ +# Conclusion + +One of the main goals of a SRE is to improve the reliability of high scale systems. Inorder to achieve this, a basic understanding of the internal workings of a system is necessary. + +Getting to know about how signals work is important since they play a big role in the lifecycle of processes. We see the use of signals in a range of operations on processes : from creating a process to killing a process. Knowledge of signals is important especially when handling them in programs. If you anticipate an event that causes signals, you can define a handler function and tell the operating system to run it when that particular type of signal arrives. + +Understanding system calls is especially useful to SRE's while debugging any Linux process. System calls provide precise knowledge of the internal functionalities of an operating system. It gives an in-depth understanding for programmers about C library functions which implement system calls at a lower level. With the use of *strace* command, one may easily debug slow or hung processes. + + + +# Further Reading + + + + + + + \ No newline at end of file diff --git a/courses/level102/system_calls_and_signals/images/Transition_between_User_and_Kernel_Mode.png b/courses/level102/system_calls_and_signals/images/Transition_between_User_and_Kernel_Mode.png new file mode 100755 index 0000000000000000000000000000000000000000..1009e95639273dea0b0c6a52d4bab45e8ea1c43b GIT binary patch literal 33642 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 Domspw literal 0 HcmV?d00001 diff --git a/courses/level102/system_calls_and_signals/intro.md b/courses/level102/system_calls_and_signals/intro.md new file mode 100644 index 0000000..8abeaee --- /dev/null +++ b/courses/level102/system_calls_and_signals/intro.md @@ -0,0 +1,29 @@ +# System Calls and Signals + +## Prerequisites + +- [Linux Basics](https://linkedin.github.io/school-of-sre/level101/linux_basics/intro/) +- [Python Basics](https://linkedin.github.io/school-of-sre/level101/python_web/intro/) + +## What to expect from this course + +The course covers a fundamental understanding of signals and system calls. It sheds light on how the knowledge of signals and system calls can be helpful for an SRE. + +## What is not covered under this course + +The course does not discuss any other interrupts or interrupt handling apart from signals. The course will not deep dive into signal handler and GNU C library. + +## Course Contents +- [Signals](https://linkedin.github.io/school-of-sre/level102/signals) + - [Introduction to interrupts and signals](https://linkedin.github.io/school-of-sre/level102/signals/#introduction-to-interrupts-and-signals) + - [Types of signals](https://linkedin.github.io/school-of-sre/level102/signals/#types-of-signals) + - [Sending signals to process](https://linkedin.github.io/school-of-sre/level102/signals/#sending-signals-to-process) + - [Handling signals](https://linkedin.github.io/school-of-sre/level102/signals/#handling-signals) + - [Role of signals in system calls with the example of *wait()*](https://linkedin.github.io/school-of-sre/level102/signals/#role-of-signals-in-system-calls-with-the-example-of-wait) +- [System calls](https://linkedin.github.io/school-of-sre/level102/system_calls) + - [Introduction](https://linkedin.github.io/school-of-sre/level102/system_calls/#introduction) + - [Types of system calls](https://linkedin.github.io/school-of-sre/level102/system_calls/#types-of-system-calls) + - [User mode,kernel mode and their transitions](https://linkedin.github.io/school-of-sre/level102/system_calls/#user-mode-kernel-mode-and-their-transitions) + - [Working of *write()* system call](https://linkedin.github.io/school-of-sre/level102/system_calls/working-of-write-system-call) + - [Debugging in Linux with strace](https://linkedin.github.io/school-of-sre/level102/system_calls/debugging-in-linux-with-strace) + diff --git a/courses/level102/system_calls_and_signals/signals.md b/courses/level102/system_calls_and_signals/signals.md new file mode 100644 index 0000000..f1d3369 --- /dev/null +++ b/courses/level102/system_calls_and_signals/signals.md @@ -0,0 +1,137 @@ +## Introduction to interrupts and signals + +An interrupt is an event that alters the normal execution flow of a program and can be generated by hardware devices or even by the CPU itself. When an interrupt occurs the current flow of execution is suspended and the interrupt handler runs. After the interrupt handler runs the previous execution flow is resumed. There are three types of events that can cause the CPU to interrupt: hardware interrupts, software interrupts, and exceptions. + +Signals are nothing but software interrupts that notifies a process that an event has occurred. These events might be requests from users or indications that a system problem (such as a memory access error) has occurred. Every signal has a signal number and a default action defined. A process can react to them in any of the following ways: + +- a default (OS-provided) way +- catch the signal and handle them in a program-defined way +- ignore the signal entirely + +## Types of signals + +To list available signals in a Linux system, you can use the command `kill -l` . +The table below lists the signals 1 to 20. To get a full list of signals, you can refer [here](https://en.wikipedia.org/wiki/Signal_(IPC)). + +| Signal name | Signal number | Default Action | Meaning | +| :------------- | :----------: | :-----------: | :-----------: | +| SIGHUP | 1 | Terminate | Hangup detected on controlling terminal or death of controlling process | +| SIGINT | 2 | Terminate | Interrupt from keyboard | +| SIGQUIT | 3 | Core dump | Quit from keyboard | +| SIGILL | 4 | Core dump | Illegal instruction | +| SIGTRAP | 5 | Core dump | Trace/breakpoint trap for debugging | +| SIGABRT , SIGIOT | 6 | Core dump | Abnormal termination | +| SIGBUS | 7 | Core dump | Bus error | +| SIGFPE | 8 | Core dump | Floating point exception | +| SIGKILL | 9 | Terminate | Kill signal(cannot be caught or ignored) | +| SIGUSR1 | 10 | Terminate | User-defined signal 1 | +| SIGSEGV | 11 | Core dump | Invalid memory reference | +| SIGUSR2 | 12 | Terminate | User-defined signal 2 | +| SIGPIPE | 13 | Terminate | Broken pipe;write pipe with no readers | +| SIGALRM | 14 | Terminate | Timer signal from alarm | +| SIGTERM | 15 | Terminate | Process termination | +| SIGSTKFLT | 16 | Terminate | Stack fault on math co-processor | +| SIGCHLD | 17 | Ignore | Child stopped or terminated | +| SIGCONT | 18 | Continue | Continue if stopped | +| SIGSTOP | 19 | Stop | Stop process (can not be caught or ignore) | +| SIGTSTP | 20 | Stop | Stop types at tty | + +## Sending signals to process + +There are three different ways to send signals to processes: + +- Sending signal to process using kill + +Kill command can be used to send signals to process. By default a SIGTERM signal is sent but a different type of signal can be sent to the process by defining the signal number(or signal name). +For example, the command `kill -9 367` sends SIGKILL to the process with PID 367 + +- Sending signal to process via keyboard + +Signals can be sent to a running process by pressing some specific keys. +For example, holding Ctrl+C sends SIGINT to the process which kills it. + +- Sending signal to process via another process + +A process can send a signal to another process via the kill() system call. +`int kill(pid_t pid, int sig)` system call takes 2 arguments, pid of the process you wish to send the signal to and the signal number of the desired signal. + +## Handling signals + +Referring to the table of signals in the previous section, you can see that there are default handlers attached to all signals when the program is started. When we invoke signal to attach our own handler, we are over-riding the default behaviour of the program in response to that signal. Specifically, if we attach a handler to SIGINT, the program will no longer terminate when you press +C (or send the program a SIGINT by any other means); rather, the function specified as the handler will be invoked instead which will define the behaviour of the program in response to that signal. + +Let’s take an example of handling SIGINT signal and terminating a program. We will use Python’s *signal* library to achieve this. + +When we press Ctrl+C, SIGINT signal is sent. From the signals table, we see that the default action for SIGINT is to terminate the process. +To illustrate how the process reacts to the default action and a signal handler, let us consider the below example. + +Default Action of SIGINT: + +Let us first run the below lines in a python environment: + +``` +while 1: + continue +``` +Now let us press "Ctrl+C". + +On pressing "Ctrl+C" , a SIGINT interrupt is sent to the process and the default action for SIGINT as per the table we saw in the previous section is to terminate the process. We see that the while loop is terminated and we get the below on our console: + +``` +^CTraceback (most recent call last): + File "", line 2, in + KeyboardInterrupt +``` + +The process terminated(default action) since it received a SIGINT(Keyboard Interrupt) when we pressed Ctrl+C. + +Signal Handler for SIGINT: + +Let us run the below lines of code in the Python environment. + +``` +import signal +import sys + +#Start of signal_handler function + +def signal_handler(signal, frame): + print ('You pressed Ctrl+C!') + +# End of signal_handler function + +signal.signal(signal.SIGINT, signal_handler) + +``` + +This is an example of a program that defines its own signal handler for SIGINT , overriding the default action. + +Now let us run the while and continue statement as we did previously. + +``` +while 1: + continue +``` + +Do we see any changes when Ctrl+C is pressed? Does the program terminate? +We see the below output: + +``` +^CYou pressed Ctrl+C! +``` +Everytime we press Ctrl+C, we just the see the above message and the program does not terminate. Inorder to terminate the program, you can press Ctrl+Z which sends the SIGSTOP signal whose default action is to stop the process. + +In the case of the signal handler, we define a function *signal_handler()* which prints “You pressed Ctrl+C!” and does not terminate the program. The handler is called with two arguments, the signal number and the current stack frame (None or a [frame object](https://docs.python.org/3/reference/datamodel.html#frame-objects)). *signal.signal()* allows defining custom handlers to be executed when a signal is received. Its two arguments are the signal number(name) you want to trap and the name of the signal handler. + +## Role of signals in system calls with the example of *wait()* + +The *wait()* system call waits for one of the children of the calling process to terminate +and returns the termination status of that child in the buffer pointed to by *statusPtr*. + +- If the parent process calls the *wait()* system call, then the execution of the parent is suspended until the child is terminated. +- At the termination of the child, a SIGCHLD signal is generated which is delivered to the parent by the kernel. SIGCHLD signal indicates to the parent that there is some information on the child that needs to be collected. +- Parent, on receipt of SIGCHLD , reaps the status of the child from the process table. Even though the child is terminated, there is an entry in the process table corresponding to the child where the process entry and PID is stored. +- When the parent collects the status, this entry is deleted. Thus, all the traces of the child process are removed from the system. + +If the parent decides not to wait for the child’s termination and it executes its subsequent task, or fails to read the exit status of the child, there remains an entry in the process table even after the termination of the child. This state of the child process is known as the Zombie state. In order to avoid long-lasting zombies, we need to have code that calls *wait()* after the child process is created. It is generally good to create a signal handler for the SIGCHLD signal, calling one of the wait-family functions in a loop, until no uncollected child data remains. + +A child process becomes orphaned, if its parent process terminates before the child .The orphaned child is adopted by init/systemd, the ancestor of all processes, whose process ID is 1. Further calls to fetch the parent pid of this process returns 1. diff --git a/courses/level102/system_calls_and_signals/system_calls.md b/courses/level102/system_calls_and_signals/system_calls.md new file mode 100644 index 0000000..28af0d3 --- /dev/null +++ b/courses/level102/system_calls_and_signals/system_calls.md @@ -0,0 +1,194 @@ +## Introduction + +A system call is a controlled entry point into the kernel, allowing a process to +request the kernel to perform some action on the process’s behalf. The kernel +makes a range of services accessible to programs via the system call application +programming interface (API). Application developers often do not have direct access to the system calls, but can access them through this API. These services include, for example, creating a new process, performing I/O, and creating a pipe for interprocess communication. The set of system calls is fixed. Each system call is identified by a unique number. The list of different system calls can be found [here](https://man7.org/linux/man-pages/man2/syscall.2.html). + +A system call changes the processor state from user mode to kernel mode, so +that the CPU can access protected kernel memory. Each system call may have a set of arguments that specify information to be transferred from user space (i.e., the process’s virtual address space) to kernel space and vice versa. From a programming point of view, invoking a system call looks much like calling a C function. + +## Types of system calls + +There are mainly 5 types of different system calls. They are : + +- Process Control: These system calls are used to handle tasks related to a process such as process creation, termination,etc. +- File Management: These system calls are used for operations on files such as reading/writing a file. +- Device Management: These system calls are used to deal with devices such as reading/writing into device buffers. +- Information Maintenance: These system calls handle information and its transfer between the operating system and the user program. +- Communication: These system calls are useful for inter-process communication. They are also used for creating and deleting a communication connection. + +| Types Of System Calls | Examples in Linux | +| :------------- | ----------: | +| Process Control | fork(),exit(),wait() | +| File Management | open(), read(),write() | +| Device Management | ioctl(),read(),write() | +| Information Maintenance | getpid(),alarm(),sleep() | +| Communication | pipe(),shmget(),mmap() | + +## User mode, kernel mode and their transitions + +Modern processor architectures typically allow the CPU to operate in at least two +different modes: user mode and kernel mode . Correspondingly, areas of virtual memory can be marked as being part of user space or kernel space. When running in user mode, the CPU can access only memory that is marked as being in user space; attempts to access memory in kernel space result in a hardware exception. + +At any given time, a process may be executing in either user mode or kernel mode. The type of instructions that can be executed depends on the mode and this is enforced at the hardware level. CPU modes (also called processor modes, CPU states, CPU privilege levels) are operating modes for the central processing unit of some computer architectures that place restrictions on the type and scope of operations that can be performed by certain processes being run by the CPU. The kernel itself is not a process but a process manager. The kernel model assumes that processes that require a kernel service use specific programming constructs called system calls. + +When a program is executed in user mode, it cannot directly access the kernel data structures or the kernel programs. When an application executes in kernel mode, however, these restrictions no longer apply. A program usually executes in user mode and switches to kernel mode only when requesting a service provided by the kernel. If an application needs access to hardware resources on the system(like peripherals,memory,disks), it must issue a system call, which causes a context switch from user mode to kernel mode. This procedure is followed when reading/writing from/to files, etc. It is only the system call itself which runs in kernel mode, not the application code. When the system call is complete, the process returns to the user mode with the return value using an inverse context switch. Apart from system calls, kernel routines can be activated in the below ways as well: + +- The CPU executing the process signals an exception , which is an unusual condition such as an invalid instruction. The kernel handles the exception on behalf of the process that caused it. +- A peripheral device issues an interrupt signal to the CPU to notify it of an event such as a request for attention, a status change, or the completion of an I/O operation. Each interrupt signal is dealt by a kernel program called an interrupt handler . Since peripheral devices operate asynchronously with respect to the CPU, interrupts occur at unpredictable times. +- A kernel thread is executed. Since it runs in kernel Mode, the corresponding program must be considered part of the kernel. + +![ ](./images/Transition_between_User_and_Kernel_Mode.png) + +In the above diagram, Process 1 in User Mode issues a system call, after which the process switches to Kernel Mode and the system call is serviced. Process 1 then resumes execution in User Mode until a timer interrupt occurs and the scheduler is activated in Kernel Mode. A process switch takes place and Process 2 starts its execution in User Mode until a hardware device raises an interrupt. As a consequence of the interrupt, Process 2 switches to Kernel Mode and services the interrupt. + +## Working of *write()* system call + +The *write()* system call writes data to an open file. + +``` +# include + +ssize_t write(int fd, void *buffer, size_t count); +``` + +*buffer* is the address of the data to be written; *count* is the number of bytes to write from buffer; and *fd* is a file descriptor referring to the file to which data is to be written. + +*write()* call writes up to *count* bytes from buffer to the open file referred to by *fd*. On success, *write()* call returns the number of bytes actually written, which may be less than *count* and returns -1 on error. When performing I/O on a disk file, a successful return from *write()* doesn’t guarantee that the data has been transferred to disk, because the kernel performs buffering of disk I/O in order to reduce disk activity and expedite *write()* calls. It simply copies data between a user-space buffer and a buffer in the kernel buffer cache. At some later point, the kernel writes (flushes) its buffer to the disk. + +If, in the interim, another process attempts to read these bytes of the file, then the kernel automatically supplies the data from the buffer cache, rather than from (the outdated contents of) the file. The aim of this design is to allow *write()* to be fast, since they don’t need to wait on a (slow) disk operation. This design is also efficient, since it reduces the number of disk transfers that the kernel must perform. + +## Debugging in Linux with strace + +*strace* is a tool used to trace the transition between user processes and the Linux kernel. Inorder to use the tool, we need ensure that it is installed in the system by running the command: + +``` +$ rpm -qa | grep -i strace + +strace-4.12-9.el7.x86_64 +``` + +If the above command does not give any output, you can install the tool via: + +`$ yum install strace` + +The functions which are a part of standard C library are known as library functions. The purposes of these functions are very diverse, including such tasks as opening a file, converting a time to a human-readable format, and comparing two character strings. Some library functions are layered on top of system calls. Often, library functions are designed to provide a more caller-friendly interface than the underlying system call. For example, the *printf()* function provides output formatting and data buffering, whereas the *write()* system call just outputs a block of bytes.The most commonly used implementation of the standard C library on Linux is the GNU C library [glibc](). + +The C programming language gives *printf()* that lets the user write data in many different formats. So printf() as a function converts your data into a formatted sequence of bytes and that calls *write()* to write those bytes onto the output. Let us examine what happens when a *printf()* statement is executed with the use of *strace* command : `strace printf %s “Hello world”` + +``` + ~]$ strace printf %s "Hello world" +execve("/usr/bin/printf", ["printf", "%s", "Hello world"], [/* 47 vars */]) = 0 +brk(NULL) = 0x90d000 +mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f8fc672f000 +access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory) +open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3 +fstat(3, {st_mode=S_IFREG|0644, st_size=98854, ...}) = 0 +mmap(NULL, 98854, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f8fc6716000 +close(3) = 0 +open("/lib64/libc.so.6", O_RDONLY|O_CLOEXEC) = 3 +read(3, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\20&\2\0\0\0\0\0"..., 832) = 832 +fstat(3, {st_mode=S_IFREG|0755, st_size=2156160, ...}) = 0 +mmap(NULL, 3985888, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7f8fc6141000 +mprotect(0x7f8fc6304000, 2097152, PROT_NONE) = 0 +mmap(0x7f8fc6504000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1c3000) = 0x7f8fc6504000 +mmap(0x7f8fc650a000, 16864, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7f8fc650a000 +close(3) = 0 +mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f8fc6715000 +mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f8fc6713000 +arch_prctl(ARCH_SET_FS, 0x7f8fc6713740) = 0 +mprotect(0x7f8fc6504000, 16384, PROT_READ) = 0 +mprotect(0x60a000, 4096, PROT_READ) = 0 +mprotect(0x7f8fc6730000, 4096, PROT_READ) = 0 +munmap(0x7f8fc6716000, 98854) = 0 +brk(NULL) = 0x90d000 +brk(0x92e000) = 0x92e000 +brk(NULL) = 0x92e000 +open("/usr/lib/locale/locale-archive", O_RDONLY|O_CLOEXEC) = 3 +fstat(3, {st_mode=S_IFREG|0644, st_size=106075056, ...}) = 0 +mmap(NULL, 106075056, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f8fbfc17000 +close(3) = 0 +open("/usr/share/locale/locale.alias", O_RDONLY|O_CLOEXEC) = 3 +fstat(3, {st_mode=S_IFREG|0644, st_size=2502, ...}) = 0 +mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f8fc672e000 +read(3, "# Locale name alias data base.\n#"..., 4096) = 2502 +read(3, "", 4096) = 0 +close(3) = 0 +munmap(0x7f8fc672e000, 4096) = 0 +open("/usr/lib/locale/UTF-8/LC_CTYPE", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) +fstat(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 1), ...}) = 0 +mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f8fc672e000 +write(1, "Hello world", 11Hello world) = 11 +close(1) = 0 +munmap(0x7f8fc672e000, 4096) = 0 +close(2) = 0 +exit_group(0) = ? ++++ exited with 0 +++ +``` + +> execve("/usr/bin/printf", ["printf", "%s", "Hello world"], [/* 47 vars */]) = 0 + +The first system call made is *execve()* and does three things: + +- The operating system (OS) stops the duplicated process (of the parent). +- OS loads up the new program (in this case: *printf()*), and starts the new program. +- *execve()* replaces defining parts of the current process's memory stack with the new stuff loaded from the *printf* executable file. + +The first word of the line, execve, is the name of the system call being executed. The first parameter must be the path of a binary executable or a script. The second is an array of argument strings passed to the new program. By convention, the first of these strings should contain the filename associated with the file being executed. The third parameter must be an environment variable. The number after the = sign (which is 0 in this case) is a value returned by the execve system call which indicates that the call was successful. + +> open("/usr/lib/locale/UTF-8/LC_CTYPE", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) + +In this line, the program tried to *open()* file */usr/lib/locale/UTF-8/LC_CTYPE*. However the system call failed (with -1 status) with the descriptive error message *No such file or directory*, as the file wasn’t found (ENOENT). + + +> brk(NULL) = 0x90d000 + +> brk(0x92e000) = 0x92e000 + +> brk(NULL) = 0x92e000 + +The system call *brk()* is used to increase or decrease the process’s data segment. It returns the new address where the data segment of the process is to end. + +> open("/lib64/libc.so.6", O_RDONLY|O_CLOEXEC) = 3 + +> read(3, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\20&\2\0\0\0\0\0"..., 832) = 832 + +In the above lines of the console output, we see that a successful *open()* call is made, followed by *read()* system call. + +In *open()*, the first parameter is the path to file which you want to use and the second parameter defines the permissions. In this example, O_RDONLY which means the file is read only and [O_CLOEXEC](https://man7.org/linux/man-pages/man2/open.2.html) which enables the close-on-exec flag for the opened file. This is useful to avoid race conditions in multithreaded programs where one thread opens a file descriptor at the same time as another thread. 3 indicates the file descriptor used to open the file. Since fd 0, 1, 2 are already taken by stdin, stdout and stderr. So first unused file descriptor is 3 in file descriptor table. + +If *open()* + +In *read()*, the first parameter is the file descriptor which is 3(the file was opened using this file descriptor by *open()*. The second parameter is the buffer to read data from and the third parameter is the length of the buffer. The return value is 832 which is the number of bytes read. + +> close(3) = 0 + +A close system call is used to close a file descriptor by the kernel. For most file systems, a program terminates access to a file in a filesystem using the close system call. 0 after the = sign indicates that the system call was successful. + +> write(1, "Hello world", 11Hello world) = 11 + +In the previous section, we described the *write()* system call and the arguments that it takes. Whenever we see any output to the video screen, it’s from the file named /dev/tty and written to stdout on screen through fd 1. The first parameter is the file descriptor , second parameter is the buffer containing the information to be written and the last parameter contains the count of characters. On success, the number of bytes written are returned (zero indicates nothing was written) which is 11 in this example. + +> +++ exited with 0 +++ + +This indicates that the program exited successfully with exit code 0. An exit code of 0 generally indicates successful execution and termination in Linux programs. + +You don't need to memorize all the system calls or what they do, because you can refer to documentation when you need to. Ensure the following package is installed before running the man command: + +``` +$ rpm -qa | grep -i man-pages + +man-pages-3.53-5.el7.noarch +``` + +Run the following `man` command with the system call name to see the documentation for that system call(for eg, execve): + +``` man 2 execve ``` + +Apart from system calls, strace can be used to detect the files that are being accessed by the program. In the above trace, we have a system call *open("/lib64/libc.so.6", O_RDONLY|O_CLOEXEC) = 3* which is opening the libc shared object /lib64/libc.so.6 which is the C implementation of various standard functions. It is the file where we see the *printf()* definition needed for printing *Hello World*. + +Strace can also be used to check if a program is hanging or stuck. When we have the trace, we can observe at which operation the program is stuck as well. Furthermore, as we go through the trace, we can also find errors(if there are any) to point out why the program is hung/stuck. Strace can be very helpful in finding the reason behind slow performance of a program. + +Alhough *strace* has the aforementioned uses to it, if you're running a trace in a production environment, strace is not a good choice. +It introduces a substantial amount of overhead. According to a performance test conducted by Arnaldo Carvalho de Melo, a senior software engineer at Red Hat, the process traced using strace ran 173 times slower, which can be disastrous for a production environment. \ No newline at end of file diff --git a/mkdocs.yml b/mkdocs.yml index c016352..94a20fc 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -86,6 +86,11 @@ nav: - Containerization With Docker: level102/containerization_and_orchestration/containerization_with_docker.md - Orchestration With Kubernetes: level102/containerization_and_orchestration/orchestration_with_kubernetes.md - Conclusion: level102/containerization_and_orchestration/conclusion.md + - System Calls and Signals: + - Introduction: level102/system_calls_and_signals/intro.md + - Signals: level102/system_calls_and_signals/signals.md + - System Calls: level102/system_calls_and_signals/system_calls.md + - Conclusion: level102/system_calls_and_signals/conclusion.md - Networking: - Introduction: level102/networking/introduction.md - Security: level102/networking/security.md