Most complete in history, no rebuttal is accepted !!!!!!! In addition, the PDF version is also given at the end of the article, remember to give a nice!! Do not just collect for zanha, the interview document of 200,000 words will also be sent to everyone!!

1. Briefly explain your understanding of concurrency and parallelism?

  1. Parallelism is when two or more events occur at the same time; Concurrency is when two or more events occur at the same time interval;

  2. Parallelism is multiple events on different entities, concurrency is multiple events on the same entity;

2, synchronous, asynchronous, blocking, non-blocking concept

Synchronization: When a synchronous call is made, the caller has to wait until the result is returned. Follow-up operations can be performed only after the notification is made.

Asynchronous: When an asynchronous procedure call is issued, the caller does not immediately get a return result. The widget that actually processes the call, when complete, notifies the caller through state, notification, and callback.

Block: The current thread is suspended until the result of the call is returned.

Non-blocking: does not block the current thread even if the result of the call is not returned.

Basic concepts of processes and threads

Process: A process is an independent unit of the system for resource allocation and scheduling, and a unit of concurrent execution in the system.

Thread: A thread is an entity of a process. It is also the basic unit of CPU scheduling and dispatch. It is a basic unit smaller than a process that can run independently, sometimes called a lightweight process or lightweight process.

What’s the difference between a process and a thread?

  1. A process is the smallest unit of resource allocation, while a thread is the smallest unit of CPU scheduling.

  2. When a process is created or destroyed, the system allocates or reclaims resources for it, and the operating system overhead is much higher than that when creating or destroying a thread.

  3. The address space of different processes is independent of each other, but threads in the same process share the same address space. Threads in one process are not visible in another process;

  4. Processes do not interact with each other, and a thread failure may cause the entire process to die;

Why there is a process, but also a thread?

Processes can run multiple programs concurrently to improve resource utilization and system throughput, but they bring some disadvantages:

  1. Processes can only do one thing at a time;

  2. If a process blocks in the process of execution, the entire process will be suspended, even if some work in the process does not depend on the waiting resource, still will not execute.

Based on the above shortcomings, the operating system introduces the thread with smaller granularity than the process, as the basic unit of concurrent execution, so as to reduce the time and space cost of concurrent execution of the program, improve the concurrent performance.

In addition, I packaged it into a PDF for easy readingDownload address:500 Backend Development Interview Questions (with answers)

6. Process state transition

A process has three states: ready, running and blocked.

  1. Ready – > Execute: For processes in the ready state, when the scheduler selects a ready process according to a selected policy and assigns a processor to it, the process changes from the ready state to the execute state;

  2. Execute – > Block: The process that is executing cannot be executed because of a waiting event, then the process changes from the execution state to the blocked state, such as the process makes input/output requests and becomes the state of waiting for external devices to transmit information, and the process becomes the state of waiting for resources (main memory space or external devices) when the request for resources (main memory space or external devices) is not satisfied. The process has a fault (program error or main memory read/write error, etc.) become waiting for intervention state, etc.

  3. Blocking – > ready. In the blocking state of the process, in the wait event has occurred, such as input/output is completed, the resources are met or when the error handling, in a wait state process does not immediately turn into execution status, but the first turn to the ready state, and then by the system process scheduling procedures at an appropriate time to convert the process execution status;

  4. Execute – > Ready: An executing process that is suspended when its time slices run out or, in systems with preemptive priority scheduling algorithms, when a higher-priority process has to run and is forced to give up processing time.

7. What are the communication modes between processes?

InterProcess Communication (IPC) refers to the transmission or exchange of information between different processes. IPC usually consists of pipes (including unnamed and named pipes), message queues, semaphores, shared storage, sockets, Streams, and so on. Socket and Streams support two IPC processes on different hosts.

The pipe

  1. It is half-duplex, with fixed read and write ends;

  2. It can only be used for communication between a parent process or a sibling process;

  3. It can be viewed as a special type of file that can be read and written using normal read, write, and other functions. But it is no ordinary file, does not belong to any other file system, and only exists in memory.

A named pipe

  1. FIFO can exchange data between unrelated processes, unlike anonymous pipes;

  2. The FIFO has a path name associated with it, and it exists in the file system as a special device file.

The message queue

  1. Message queues, which are linked tables of messages, are stored in the kernel. A message queue is identified by an identifier ID;

  2. Message queues are record-oriented, where messages have a specific format and a specific priority;

  3. Message queues are independent of the sending and receiving processes. Message queues and their contents are not deleted when a process terminates;

  4. Message queues allow random query of messages, which do not have to be read in first-in, first-out order, but can also be read by message type.

A semaphore

  1. A semaphore is a counter. Used to achieve mutual exclusion and synchronization between processes, rather than for storage of inter-process communication data;

  2. Semaphores are used for interprocess synchronization, and data transfer between processes needs to be combined with shared memory.

  3. The semaphore is based on the PV operation of the operating system, and the operation of the program on the semaphore is atomic operation;

  4. Each PV operation on the semaphore is not limited to the addition or subtraction of 1 to the signal magnitude, but can be added or subtracted from any positive integer;

  5. Support for semaphore groups.

The Shared memory

  1. Shared Memory, where two or more processes share a given storage area;

  2. Shared memory is the fastest type of IPC because the process accesses memory directly.

8. What are the process scheduling algorithms?

A scheduling algorithm is a resource allocation algorithm based on the system resource allocation policy. The commonly used scheduling algorithms include: first come, first serve scheduling algorithm, time slice rotation scheduling algorithm, short job first scheduling algorithm, shortest remaining time first, high response ratio first scheduling algorithm, priority scheduling algorithm and so on.

  • First come, first serve scheduling algorithm

The first-come-first-served scheduling algorithm is one of the simplest scheduling algorithms, also known as first-in-first-out or strict queuing schemes. When each process is ready, it joins the ready queue. The process that is currently running stops execution, and the process that has been in the ready queue for the longest time is selected to run. This algorithm can be used for both job scheduling and process scheduling. First come, first go services are more suitable for routine jobs (processes) than segment jobs (processes).

  • Time slice rotation scheduling algorithm

Time slice rotation scheduling algorithm is mainly applicable to time sharing system. In this algorithm, all ready processes are queued according to the order of arrival time. The process scheduler always selects the first process in the ready queue to execute, that is, the principle of first come, first served, but only one time slice can be run.

  • Short job priority scheduling algorithm

Short job first scheduling algorithm refers to the algorithm of scheduling short jobs first. One or several jobs with the shortest estimated running time are selected from the backup queue and they are transferred to memory for running. The short-job first scheduling algorithm is a non-preemptive strategy. Its principle is to select the process with the shortest expected processing time next time, so the short process will skip the long job and jump to the head of the queue.

  • Minimum remaining time priority scheduling algorithm

Minimum remaining time is the version with preemption added for the shortest process first. In this case, the process scheduler always selects the process with the shortest expected remaining time. When a process joins the ready queue, it may have less time left than the currently running process, so as soon as the new process is ready, the scheduler can preempt the currently running process. Like shortest process first, the scheduler must have an estimate of processing time if it is executing the selection function, and there is a risk of long process starvation.

  • High response ratio priority scheduling algorithm

The high response ratio priority scheduling algorithm is mainly used for job scheduling. The algorithm is a comprehensive balance between the first-come-first-service scheduling algorithm and the short job priority scheduling algorithm, and considers the waiting time and estimated running time of each job. In each job scheduling, the response ratio of each job in the backup job queue is calculated, and the job with the highest response ratio is selected to run.

  • Priority scheduling algorithm

The priority scheduling algorithm selects one or more jobs with the highest priority from the backup job queue at a time, pulls them into memory, allocates the necessary resources, creates processes, and places them in the ready queue. In process scheduling, the priority scheduling algorithm selects the process with the highest priority from the ready queue every time, assigns the processor to it, and makes it run.

What is deadlock?

Deadlock refers to a deadlock caused by multiple processes competing for resources during the running process. When a process is in this deadlock state, it cannot move forward without external force. As shown in the figure below, if A thread, A, already holds lock A, tries to acquire lock B, and thread B holds lock B and tries to acquire lock A, A deadlock occurs.

10. What causes deadlocks?

A deadlock occurs when two or more processes occupy their own resources and request each other’s resources, causing each process to be unable to move forward due to some inalienable resources in the system.

  • Compete for resources

For example, there is only one printer on the system and process A can use it. Assume that process A has occupied the printer. If process B continues to ask the printer to print, it will be blocked.

Resources in the system can be divided into two categories:

  1. Deprived resources: After a process obtains such resources, the resources can be deprived by other processes or systems. Both CPU and main memory are deprived resources.

  2. Inalienable resources. After allocating resources to a process, the system can only release resources after the process is used up. For example, a tape drive or a printer.

  • The process is in the wrong order

For example, process A and process B wait for each other’s data.

11. What are the necessary conditions for deadlock?

  1. Mutual exclusion: Processes require exclusive control over allocated resources. That is, only one process can use a certain resource for a certain period of time.

  2. Request and hold conditions: When a process is blocked by a request for a resource, it holds a resource that has been obtained.

  3. Non-deprivation condition: The process cannot deprive the resources it has obtained before using them, and can only release them by itself when they are used up.

  4. Loop wait condition: When a deadlock occurs, there must be a loop chain of process-resources.

12. How to solve deadlock?

  1. Deadlock prevention

  2. Avoid deadlock

  3. Detection of deadlock

  4. To remove a deadlock

How to prevent deadlock?

  1. Break request conditions: Allocate all resources at once so no more requests are made;

  2. Keep the condition that no other resource is allocated to the process as long as one resource is not allocated:

  3. Breaking an inalienable condition: when a process gets some resources but does not get others, it releases the resources it already owns;

  4. Destruction-loop wait condition: the system assigns a number to each type of resource, and each process requests the resource in ascending order, and the reverse is true for release.

14. How to avoid deadlock?

1. Security status

In Figure A, the second column Has represents the number of resources already owned, the third column Max represents the total number of resources needed, and the third column Free represents the number of resources still available. Start from Figure A, let B have all the resources required (Figure B) first, and release B after running, at which time Free becomes 5 (Figure C); Then run C and A in the same way so that all processes can run successfully, and thus the state shown in Figure A can be called safe.

Definition: A state is safe if no deadlock occurs and there is still some scheduling order that allows each process to complete even if all processes suddenly request the maximum demand for resources.

The detection of a security state is similar to the detection of a deadlock because the security state must require that no deadlocks occur. The following banker algorithm is very similar to the deadlock detection algorithm and can be used as a reference.

2. Single resource banker algorithm

A banker in a small town promises a certain amount of money to a group of customers, and what the algorithm has to do is decide whether it is unsafe to meet the request, and if so, reject it; Otherwise it will be allocated.

Figure C is an unsafe state, so the algorithm will reject previous requests to avoid entering the state in Figure C.

3. Multiple resource banker algorithm

In the figure above, there are five processes and four resources. The left graph shows the resources that have been allocated, and the right graph shows the resources that still need to be allocated. The rightmost E, P, and A represent total resources, allocated resources, and available resources, respectively. Note that these three are vectors rather than specific values. For example, A=(1020), which means that the four resources have 1/0/2/0 left respectively.

The algorithm to check whether a state is safe is as follows:

  • Let’s find out if the right-hand side has A row that is less than or equal to vector A. If no such row exists, then the system will deadlock and the state is unsafe.
  • If such A line is found, mark the process as terminated and add its allocated resources to A.
  • Repeat the above steps until all processes are marked for termination and the state is safe.

If a state is not secure, you need to deny entry to that state.

In addition, I packaged it into a PDF for easy readingDownload address:500 Backend Development Interview Questions (with answers)

How to remove a deadlock?

  1. Resource deprivation: suspends some deadlocked process and preempts its resources to allocate them to other deadlocked processes (but should prevent the suspended process from being deprived of resources for a long time);

  2. Process cancellation: Force partial or even complete cancellation of deadlocked processes and deprive them of resources (the principle of cancellation can be based on process priority and the cost of cancellation);

  3. Process rollback: Let one or more processes fall back enough to avoid deadlock. When a process rolls back, it voluntarily releases resources rather than being deprived of them. The system is required to keep the process historical information and set the restore point.

16. What is a buffer overflow? What are the hazards?

A buffer is memory that temporarily holds output or input data. A buffer overflow is when the computer fills a buffer with data that exceeds the buffer’s capacity, overwriting legitimate data. The main cause of buffer overflow is that the program does not carefully check whether the user input is reasonable. On a computer, a buffer overflow can cause two main hazards: a program crash that leads to denial of service and jump and execute a malicious code.

What’s the difference between pagination and segmentation?

  1. Segment is a logical unit of information, which is divided according to the needs of the user, so the segment is visible to the user; Page is the physical unit of information, is for the convenience of managing main memory and partition, is transparent to the user;

  2. The size of a segment is not fixed, depending on the function it performs; Page size fixed, determined by the system;

  3. Segments provide the user with a two-dimensional address space; Pages provide users with a one-dimensional address space;

  4. Segment is the logical unit of information, convenient for storage protection and information sharing, page protection and sharing are limited.

18, physical address, logical address, virtual memory concept

  1. Physical address: it is the final address of address translation, the process at run time to execute instructions and access data finally from the physical address from main memory access, is the real address of the memory unit.

  2. Logical address: refers to the address that the computer user sees. For example, when creating an array of integers of length 100, the operating system returns a logically contiguous space: a pointer to the memory address of the first element in the array. Since the size of an integer element is 4 bytes, the address of the second element is the starting address plus 4, and so on. In fact, the logical address is not necessarily the real address of the element storage, that is, the physical address of the array elements (in the memory of the location), is not continuous, but the operating system through address mapping, the logical address mapping into a continuous, which is more in line with people’s intuitive thinking.

  3. Virtual memory: a technique for memory management in computer systems. It causes an application to think that it has continuous available memory (a continuous complete address space), when in fact it is usually separated into multiple physical memory fragments, with parts temporarily stored on external disk storage for data exchange as needed.

19. What are the page replacement algorithms?

Paging request, also known as paging on demand, refers to the “page” that is not in memory, when the process is executing to call in time, otherwise may not be called to the end of the program. While there is a limited amount of space in memory for pages, pages are placed in frames in memory. Request to prevent the paging process appears too much memory page fault (namely the need of the current page is not in memory, need to read data from the hard disk, means you need to do to replace) of the page and make the program execution efficiency drop, we need to design some page replacement algorithm, page according to these algorithms when replacing each other, can try to achieve low error rate. Commonly used page replacement algorithm is as follows:

  • First In First Out Permutation algorithm (FIFO)

First in first out, that is to eliminate the earliest page.

  • Optimal permutation algorithm (OPT)

Selecting the pages that will be used furthest in the future is an optimal scheme, which can prove that the missing pages are the smallest.

  • Most recently unused (LRU) algorithm

That is, choose the most recent unused pages to be eliminated

  • Clock replacement algorithm

The clock replacement algorithm is also called NRU (Not RecentlyUsed). The algorithm sets one access bit for each page and chains all pages in memory into a circular queue through link Pointers.

Talk about your understanding of dynamic link library and static link library.

Static linking is to directly copy the required execution code to the call when compiling the link. The advantage is that when the program is distributed, it does not need to rely on the library, that is, it no longer needs to be distributed with the library. The program can be executed independently, but the volume may be relatively large.

Dynamic linking is not directly copy the executable code at compile time, but by recording a series of symbols and parameters, or load the program is run when the information is passed to the operating system, operating system is responsible for the need of dynamic libraries loaded into memory, then the program is running to the specified code, share it to perform dynamic libraries are loaded in memory executable code, The end result is a run-time connection. The advantage is that multiple programs can share the same piece of code without the need to store multiple copies on disk. The disadvantage is that because it is loaded at runtime, it may affect the performance of the program in the early execution

What is the difference between an external interrupt and an exception?

An external interrupt is an event caused by something other than an instruction executed by the CPU. For example, an I/O completion interrupt indicates that the device input/output processing has completed and the processor is able to send the next input/output request. There are also clock interrupts, console interrupts, and so on.

The exception is caused by the internal events of the CPU execution instructions, such as illegal opcodes, addresses out of bounds, and arithmetic overflow.

How much can you say about the complete process of a program from start to finish?

Four processes:

(1) Precompilation mainly deals with precompiled instructions beginning with “#” in source code files. The processing rules are shown below

Delete all #define and expand all macro definitions.

Handle all conditional precompiled instructions such as “#if”, “#endif”, “#ifdef”, “#elif” and “#else”.

3. Handle the “#include” precompile directive and replace the contents of the file in its place. This process is done recursively, and the file contains other files.

4, delete all comments, “//” and “/**/”.

Keep all #pragma directives that are needed by the compiler. For example, #pragma once is used to prevent files from being re-referenced.

6, add line number and file id, easy to compile the compiler to generate debugging line number information, and compile compile error or warning is able to display the line number.

(2) Compile the xxx.I or XXx. II file generated after the precompilation, perform a series of lexical analysis, syntax analysis, semantic analysis and optimization, and generate the corresponding assembly code file.

1, lexical analysis: using an algorithm similar to the “finite state machine”, the source code program is input into the scanner, and the character sequence is divided into a series of tokens.

2. Syntax analysis: The parser analyzes the symbols generated by the scanner and generates a syntax tree. The syntax tree output by the parser is a tree with expressions as nodes.

3. Semantic analysis: The parser only completes the analysis on the grammar level of the expression. The semantic analyzer determines whether the expression is meaningful or not.

Optimization: an optimization process at the source code level.

5. Object code generation: The code generator converts the intermediate code into the target machine code and generates a series of code sequences — assembly language representation.

6. Object code optimization: The object code optimizer optimizes the above target machine code by finding appropriate addressing methods, using displacement instead of multiplication, removing redundant instructions, etc.

(3) Compilation

Convert assembly code into instructions (machine code files) that can be executed by the machine. Compared with the compiler, the assembly process of the assembler is simpler. There is no complex syntax, no semantics, and no need to do instruction optimization. It is just translated one by one according to the comparison table of assembly instructions and machine instructions.

After compilation, the object files (in almost the same format as executable files)xxx.o(under Linux), xxx.obj(under Windows) are produced.

(4) Links

Link object files from different source files to form an executable program. Links are divided into static links and dynamic links:

Static linking: Functions and data are compiled into a binary file. In the case of static libraries, when the linked executable is compiled, the linker copies these functions and data from the library and combines them with other modules of the application to create the final executable. Waste of space: Because each executable program must have a copy of all the required object files, so if multiple programs have dependencies on the same object file, there will be multiple copies of the same object file in memory; Update difficulty: Whenever the code of a library function is changed, it needs to be recompiled and linked to form an executable.

Run fast: But the advantage of static linking is that the executable already has everything it needs to run, and runs fast when it executes.

2. Dynamic link: The basic idea of dynamic link is to divide the program into relatively independent parts according to modules, and link them together to form a complete program when the program is running, rather than link all program modules into a single executable file like static link.

Shared libraries: even if every program needs to rely on the same library, the library does not have multiple copies in memory like static linking. Instead, the same copy is shared by all programs when executed.

Easy to update: update only need to replace the original object file, without the need to link all the programs again. The next time the program runs, the new version of the object file is automatically loaded into memory and linked, and the program has completed the upgrade.

Performance penalty: There is a performance penalty because the link is delayed until the program is running, so it needs to be linked every time the program is executed.

In addition, I packaged it into a PDF for easy readingDownload address:500 Backend Development Interview Questions (with answers)

23. Introduce some typical locks?

Read-write lock
  • Multiple readers can read at the same time
  • Writers must be mutually exclusive (only one writer is allowed to write, and neither reader writer is allowed to write simultaneously)
  • The writer takes precedence over the reader (once there is a writer, subsequent readers must wait, and the writer takes precedence when awakened)
The mutex

Only one thread can have a mutex at a time; the other threads have to wait

Mutex is in the lock failed initiative to give up the CPU to sleep until the lock state changes to wake up again, and the operating system is responsible for thread scheduling, in order to realize the state of the lock wake blocked thread or process change, need to lock to the operating system management, so the mutex locking operation involving the context switch. Mutex actual efficiency is still acceptable, lock time probably around 100 ns, but in fact the mutex is one possible realization of spin for a period of time, when the spin time exceeds a threshold and then put the thread into sleep, so in the concurrent operation using a mutex (each holding time is very short) may as using a spin lock

Condition variables,

An obvious drawback to mutex is that it has only two states: locked and unlocked. Condition variables compensate for a mutex by allowing one thread to block and wait for another thread to send a signal. They are often used in conjunction with a mutex to prevent race conditions. When a condition is not met, the thread often unlocks the corresponding mutex, blocks the thread and waits for the condition to change. Once one of the other threads changes the condition variable, it tells the corresponding condition variable to wake up one or more threads that are blocked by the condition variable. In general, mutex is the mechanism of mutual exclusion between threads, and condition variables are the mechanism of synchronization.

spinlocks

If the incoming thread cannot acquire the lock, the incoming thread does not immediately give up the CPU time slice, but keeps trying to acquire the lock in a loop until it does. If another thread holds the lock for a long period of time, spin is a waste of CPU work, but spin locks are more efficient when the lock time is short.

24. What is user mode and kernel mode

User mode and kernel mode are two operating system running states.

  • Kernel mode: The CPU in the kernel mode can access any data, including peripheral devices, such as network cards, hard disks, etc. The CPU in the kernel mode can switch from one program to another program, and no preemption occurs when the CPU is occupied. In general, the CPU in the privilege level 0 state is called the kernel mode.
  • User mode: A CPU in user mode has limited memory access and is not allowed to access peripheral devices. A CPU in user mode is not allowed to be exclusive, that is, the CPU can be accessed by other programs.

So why have user mode and kernel mode?

The main concern is the limitation of access, there are some dangerous computer operations, such as setting the clock, memory cleaning, these need to be done in kernel mode, if you do these operations at will, how many times your system will crash.

How to switch between user mode and kernel mode?

All user processes run in user mode, but as we mentioned above, user programs have limited access. Some important operations, such as reading data from the hard disk or retrieving data from the keyboard, are only done in kernel mode, and these data are very important to user programs. So it involves switching between two modes, user mode -> kernel mode -> user mode, and the only thing that can do that is the system call, and the only thing that can do that is the operating system.

General user -> kernel mode conversion we are called trap into the kernel, also known as trap instructions (trap instruction).

Here’s how they work:

  • First the user program callsglibcGlibc is a standard library as well as a set of core libraries that define many key apis.
  • The GLIBC library is aware of calls to different architecturesThe system callsWhich prepares the system call by setting the parameters passed by the user process according to the binary interface of the architectural application.
  • The GliBC library is then calledSoftware Interrupt instruction (SWI), this directive is updated byCPSRRegister changes the mode to superuser mode and jumps to the address0x08Place.
  • So far, the entire process has remained in user mode, allowing the process to execute kernel code after executing SWI instructions, and the MMU now allows kernel virtual memory access
  • Starting at address 0x08, the process performs the load and jumps to the interrupt handler, which is in ARMvector_swi().
  • At vector_swi(), extract the system call number SCNO from the SWI instruction, and then use SCNO as the system call tablesys_call_tableTo the system call function.
  • After executing the system call, the user mode register is restored and executed again in user mode.

26. How the process terminates

Process termination

After the process is created, it runs and completes the task. However, nothing goes on forever, including progress. A process terminates sooner or later, but it is usually triggered by the following

  • Normal withdrawal (voluntary)
  • Exit by mistake (voluntary)
  • Serious error (involuntary)
  • Killed by another process (involuntarily)

The normal exit

Most processes terminate when they have completed their work. When the compiler has finished compiling a given program, it makes a system call to tell the operating system that it has done its job. This call is exit in UNIX and ExitProcess in Windows. On-screen software also supports voluntary termination. Word processors, Internet browsers, and similar programs always have an icon or menu item that the user clicks to notify the process to delete any temporary files it has locked open and then terminate.

Error to exit

The second reason a process terminates is if a critical error is found, for example, if the user executes the following command

cc foo.c
Copy the code

In order to compile foo.c but the file does not exist, the compiler will issue a declaration and exit. When error parameters is given, for interactive process usually does not directly out of the screen, because it is not reasonable from the view of the user, the user needs to know what happened and want to try again, so the application usually will pop up a dialog box to inform the user system error occurred, it is need to retry or quit.

Serious mistakes

A third cause of process termination is an error caused by the process, usually due to an error in the program. For example, an illegal instruction was executed, a reference to memory that does not exist, or the divisor is zero. On some systems, such as UNIX, a process can notify the operating system that it wants to handle a certain type of error by receiving a signal (an interrupt), rather than terminating the process when such an error occurs.

Killed by another process

A fourth reason to kill a process is when a process makes a system call telling the operating system to kill a process. In UNIX, this system call is kill. The Win32 equivalent is TerminateProcess (note that it is not a system call).

27. Daemons, zombie processes and orphan processes

daemon

A process that runs in the background and is not connected to a control terminal. It performs a task periodically, independent of the control terminal. Most servers on Linux are implemented as daemons, such as the Web server process HTTP

Tips for creating a daemon:

(1) Let the program run in the background. This is done by calling fork () to produce a child process and then causing the parent process to exit.

(2) Call setsid () to create a new dialog. Control terminals, login sessions, and process groups are usually inherited from the parent process, and the daemon can get rid of them, unaffected by them, by calling setsid () to make the process a session leader. After a successful setsid () call, the process becomes the new session leader and process leader and disconnects from the original login session, process group, and control terminal.

(3) Disable the process from reopening the control terminal. After the above steps, the process has become a terminal free session leader, but it can re-request to open a terminal. This can be avoided by making the process no longer the session leader. Create a new child process by fork () again, causing the process that called fork to exit.

(4) Close file descriptors that are no longer needed. The child process inherits the open file descriptor from the parent. If it is not closed, system resources are wasted, the file system where the process is running cannot be unloaded, and unexpected errors occur. First get the highest file descriptor value, then use a loop program to close all file descriptors from 0 to the highest file descriptor value.

Change the current directory to the root directory.

(6) File creation masks that children inherit from their parents may deny certain permissions. To prevent this, use unmask (0) to clear the mask word to zero.

(7) Process SIGCHLD signal. For server processes, child processes are often generated to handle requests when they arrive. If the child process waits for the parent process to capture the state, the child process becomes a zombie and consumes system resources. If the parent process waits for the child process to finish, the burden on the parent process will be increased and the concurrent performance of the server process will be affected. Under Linux you can simply set the SIGCHLD signal’s operation to SIG_IGN. This way, a child process terminates without spawning a zombie.

An orphan

If the parent exits before the child exits, the child’s parent becomes an init process. (Note: any process must have a parent).

If a parent exits while one or more of its children are still running, those children become orphans. The orphan processes will be adopted by the init process (process number 1), and the init process will do the state collection on them.

zombies

If the child exits before the parent exits, the child must wait until the parent captures the child’s exit status before the child is truly finished, otherwise the child becomes a zombie.

The purpose of setting up a zombie process is to maintain information about the child process for the parent process to obtain at a later time. At a minimum, this information includes the process ID, the process’s termination status, and the CPU time used by the process, so it is available when the parent of the terminating child process calls WAIT or WaitPID. If a process terminates and that process has children in zombie state, the parent process ID of all of its zombie children is reset to 1 (init process). The init process that inherits these children will clean them up (that is, the init process will wait for them, thereby removing their zombie state).

28. How to avoid zombie processes?

  • Signal (SIGCHLD, SIG_IGN) is used to notify the kernel that it does not care about the end of the child process. If you don’t want the parent process to suspend, you can add a statement to the parent process: signal(SIGCHLD,SIG_IGN); Indicates that the parent process ignores the SIGCHLD signal that is sent to the parent process when the child process exits.
  • The parent process calls the wait/waitpid function to wait for the child process to finish. If no child process exits the wait, the parent process will block. Waitpid can be passed WNOHANG so that the parent process returns immediately without blocking.
  • If the parent is busy, register the signal handler with signal and wait for the child to exit by calling wait/ waitPID.
  • By calling fork twice. The parent process first calls fork to create a child process. Then waitpid waits for the child process to exit. The child process then forks a child process and exits. In this case, when the parent process exits, the parent process waits for collection, and when the parent process exits, the grandchild process becomes an orphan process. The orphan process is taken over by init process, and when the grandchild process finishes, init waits for collection.

The first method ignores the SIGCHLD signal, which is often used as a performance trick for concurrent servers because concurrent servers often fork many child processes, which require the server process to wait to clean up resources after the child process terminates. If the signal processing mode is set to ignore, the kernel can transfer the zombie subprocess to the init process to handle, which saves a lot of zombie processes occupying system resources.

Common memory allocation memory errors

(1) Failed to allocate memory, but used it.

New programmers often make this mistake because they don’t realize that memory allocation can be unsuccessful. A common solution is to check whether the pointer is NULL before using memory. If the pointer p is an argument to the function, assert(p! =NULL). If you use malloc or new, you should use if(p==NULL) or if(p! =NULL).

(2) The memory allocation is successful, but the reference is not initialized.

There are two main reasons to make this mistake: first, there is no concept of initialization; The second is that the default initial value of memory is all zero, resulting in an error reference to the initial value (such as array). There is no consensus on what the initial default value for memory is, and although it is sometimes zero, we prefer to believe that there is no default value. So no matter how you create an array, don’t forget to assign the initial value, even if it’s zero, don’t bother.

(3) The memory was allocated successfully and initialized, but the operation crossed the memory boundary.

For example, it is common to subscript “more than 1” or “less than 1” when using arrays. In particular, in a for loop, it’s easy to get the wrong number of loops, causing array operations to overshoot.

(4) Forget to release memory, resulting in memory leak.

A function that contains this error loses a chunk of memory every time it is called. The system has plenty of memory to start with, and you don’t see any errors. Finally, once the program suddenly crashed, the system appeared: memory is running out. The application and release of dynamic memory must be paired, and malloc and free must be used the same number of times in the program, otherwise there must be an error (same with new/delete).

(5) Free memory but continue to use it. There are three common conditions:

  • The object calling relationship in the program is too complex, and it is difficult to know whether an object has freed memory. At this time, the data structure should be redesigned to fundamentally solve the chaotic situation of object management.
  • Do not return a “pointer” or “reference” to “stack memory”, as this memory will be destroyed at the end of the function body.
  • After free or DELETE is used to free memory, the pointer is not set to NULL. An “wild pointer” is generated.

In memory swapping, where is the process to be swapped out saved?

Stored on disk, that is, in external storage. In an operating system with swap function, the disk space is usually divided into file area and swap area. The file area is mainly used for storing files, and the utilization of storage space is mainly pursued. Therefore, the management of the file area space adopts the discrete allocation mode. The swap area occupies only a small part of the disk space, and the data of the process that is swapped out is stored in the swap area. Since the speed of swap directly affects the overall speed of the system, the management of swap space mainly pursues the speed of swap in and out, so the continuous allocation mode is usually adopted for swap area (can be understood after learning the chapter of file management). In general, I/O in swap partitions is faster than in file partitions.

How is the atomic operation implemented

** Processors use caching based locking or bus based locking for atomic operations between multiple processors. ** First, the processor automatically guarantees atomicity for basic memory operations. The processor guarantees that reading or writing a byte from system memory is atomic, meaning that when one processor reads a byte, the memory address of that byte cannot be accessed by other processors. Pentium 6 and newer processors can automatically guarantee atomicity for 16/32/64 bit operations performed by a single processor on the same cache row, but processors cannot automatically guarantee atomicity for complex memory operations, such as access across bus widths, across multiple cache rows, and across page tables. However, processors provide both bus locking and cache locking mechanisms to ensure atomicity of complex memory operations.

(1) Atomicity with bus locks The first mechanism to ensure atomicity is through bus locks. If multiple processors read and rewrite a shared variable at the same time (i++ is classic read and rewrite), then the shared variable will be read and rewrite by multiple processors at the same time, so the read and rewrite is not atomic, and the value of the shared variable will not match the expected value after the operation. For example, if I =1 and we perform I ++ twice, we expect the result to be 3, but it could be 2, as shown in the figure below.

CPU1    CPU2
 i=1     i=1
 i+1     i+1
 i=2     i=2Copy to clipboardErrorCopied
Copy the code

The reason may be that multiple processors simultaneously read the variable I from their respective caches, incrementing each variable by 1, and then separately writing it to system memory. So, to ensure that the read-rewrite operations on a shared variable are atomic, you must ensure that CPU1 reads and overwrites the shared variable, and CPU2 does not operate the cache that caches the memory address of the shared variable.

The processor uses bus locks to solve this problem. A bus lock is the use of a LOCK# signal provided by the processor. When one processor outputs this signal on the bus, requests from other processors will be blocked and the processor will have exclusive access to shared memory.

The second mechanism is to ensure atomicity through cache locking. At the same time, we just can assure the operation of a particular memory address is atomic, but the bus lock lock of communication between the CPU and memory, which makes the lock period, the other processors can not operate other memory address data, so the bus locking overhead is large, the current processor cache lock in certain situations instead of bus lock to optimization.

Frequently used memory is cached in the processor’s L1, L2, and L3 caches, so atomic operations can be performed directly in the processor’s internal cache without the need to declare a bus lock. In Pentium 6 and current processors, complex atomicity can be achieved using a “cache lock” approach.

“Cache Lock” refers to the memory area if the cached processor cache line, and is locked during the Lock operation, so when it performs Lock operations back to writes to the memory, the processor do not claim to LOCK# signals on the bus, but modify the internal memory addresses, and allow it to the cache consistency mechanism to ensure the atomicity of operation, Because the cache consistency mechanism can prevent and modify by two or more data processor cache memory area, while the rest of the processor to write cache the data has been locked, can make the cache line is invalid, in as shown in the above example, when the CPU1 revisions in the cache line I used the cache lock, so CPU2 can’t use cache I cache line at the same time.

But there are two situations where the processor does not use cache locking. In the first case, the processor calls a bus lock when the data being manipulated cannot be cached inside the processor, or when the data being manipulated spans multiple cache lines. The second case is that some processors do not support cache locking. For Intel 486 and Pentium processors, bus locking is called even if the locked memory area is in the processor’s cache line.

Do you know what it is? It’s also called bumping

This frequent page scheduling behavior is called jitter, or jolting, when a page that has just been swapped out is immediately swapped out of memory and a page that has just been swapped out of external storage. The main cause of jitter is that the number of pages frequently accessed by the process is higher than the number of physical blocks available (there are not enough physical blocks allocated to the process)

Too few physical blocks are allocated to the process, which causes process jitter. In order to study how many physical blocks should be allocated to each process, Denning introduced the concept of “process working set”

In addition, I packaged it into a PDF for easy readingDownload address:500 Backend Development Interview Questions (with answers)

What is the problem, can be @ handsome, feel good, ask comment Pointers and thumbs up

Recommended Reading:

Java basic interview questions reading guide

Java Unusual interview questions reading guide

Java collection interview questions reading guide

Java and test reading guide

JVM interview questions reading Guide

The SSM Framework interview questions reading guide

Operating System Interview Questions Reading Guide (must see)

Computer Network Interview Questions Reading Guide (must see)

Java Interview Questions Reading Guide (must see)

MySQL Interview Questions Reading Guide (must see)

Redis Interview Questions Reading Guide (must see)

Message Queues and Zookeeper Interview Questions Reading Guide (Must see)