Article count:1382 Read by:1966155

Account Entry

Embedded written test and interview questions series (summary)

Latest update time:2024-06-04
    Reads:

This series organizes the questions by category, which helps everyone have a complete understanding of the embedded written test and interview framework.

1. Processes and threads

1. What are processes and threads? What are the differences?

A process is the basic unit of resource (CPU, memory, etc.) allocation, and a thread is the basic unit of CPU scheduling and allocation (the smallest unit of program execution). At the same time, if the CPU is single-core, only one process is executing. The so-called concurrent execution is also sequential execution, but because the switching speed is too fast, you think these processes are executing synchronously. A multi-core CPU can have multiple processes executing at the same time.

2. Advantages and disadvantages of multi-process and multi-threading

Description: A process consists of a process control block, a data segment, and a code segment. The process itself cannot run programs, but is like a container. First, a main thread is created and certain system resources are allocated to the main thread. At this time, various functions can be implemented in the main thread. When we need to implement more complex functions, we can create multiple sub-threads in the main thread. Multiple threads in the same process use the system resources owned by the process to cooperate to complete certain functions.

Advantages and disadvantages: 1) The death of a process does not affect other processes, but the crash of a thread is likely to affect the entire process in which it is located. 2) The system cost of creating multiple processes is greater than that of creating multiple threads. 3) Multi-process communication is not suitable for the transmission of large amounts of data because it needs to cross process boundaries, but is suitable for the transmission of small or dense data. Multithreading does not need to cross process boundaries and is suitable for the transmission of large amounts of data between threads. In addition, multiple threads can share shared memory and variables in the same process.

3. When to use processes and when to use threads

1) Threads are used frequently when creating and destroying processes, because the cost of creating processes is high. 2) Threads are used when large amounts of data need to be transferred, because multi-threaded switching is fast and does not require crossing process boundaries. 3) Safe and stable process selection; fast and frequent thread selection;

4. Multi-process and multi-thread synchronization (communication) methods

Inter-process communication:

(1) Named pipe/unnamed pipe (2) Signal (3) Shared memory (4) Message queue (5) Semaphore (6) Socket

Thread communication (lock):

(1) Semaphore (2) Read-write lock (3) Condition variable (4) Mutex lock (5) Spin lock

5. State transition diagram of process thread

(1) Ready state: The process has obtained all necessary resources except the CPU and is only waiting for the CPU. A system will arrange multiple processes in the ready state into a ready queue.

(2) Execution state: The process has obtained the CPU and is being executed. In a single-processor system, there is only one process in the execution state; in a multi-processor system, there are multiple processes in the execution state.

(3) Blocked state: The executing process cannot continue to execute for some reason, so it abandons the processor and is in a suspended state, that is, the process execution is blocked. (This state is also called waiting state or blocking state)

Typical events that usually cause process blocking include: requesting I/O, applying for buffer space, etc.

Generally, processes in a blocked state are arranged into a queue. Some systems also arrange these blocked processes into multiple queues according to the different reasons for the blocking.

(1) Ready → Execute

A process in the ready state will change from the ready state to the executing state when the process scheduler allocates a processor to it.

(2) Execute → Ready

During its execution, a process in the executing state has to give up the processor because a time slice allocated to it has been used up, so the process changes from the executing state to the ready state.

(3) Execute → Block

When a process that is being executed cannot continue to execute because it is waiting for a certain event to occur, it changes from the executing state to the blocked state.

(4) Blocked → Ready

If the event that a process is waiting for has occurred, the process changes from the blocked state to the ready state.

6. Parent process, child process

After the parent process calls fork(), a child process is cloned. The child process and the parent process have the same code segment, data segment and user stack. It is not certain which of the parent process and the child process will be executed first, depending on the CPU. Therefore, we usually set the parent process to wait for the child process to finish executing.

7. Explain what is context switching?

You can have many angles, there is process context, there is interrupt context.

Process context: When a process is executing, the values ​​in all CPU registers, the state of the process, and the contents of the stack. When the kernel needs to switch to another process, it needs to save all the states of the current process, that is, save the process context of the current process, so that when the process is executed again, it can restore the state at the time of switching and continue execution.

Interrupt context: Due to the trigger signal, the CPU interrupts the current process and executes another program instead. Then all the resources of the current process must be saved, such as the stack and pointer. After saving, the interrupt handler is executed, and the execution is completed and returned. After returning, the resources of the previous process are restored and the execution continues. This is the context of the interrupt.

2. C/C++ Questions

1. new and malloc

When working in embedded systems, you are very concerned about memory. Since available memory is limited, memory questions frequently appear in embedded system written and interview tests.

1) malloc and free are library functions of C++/C language, which require header file support stdlib.h; new and delete are keywords of C++, which do not require header files but require compiler support;

2) When using the new operator to request memory allocation, there is no need to specify the size of the memory block, the compiler will calculate it based on the type information. However, malloc requires explicit support for the required memory size.

3) When the new operator allocates memory successfully, it returns a pointer of the object type, which strictly matches the object and does not require type conversion. Therefore, new is a type-safe operator. When malloc allocates memory successfully, it returns a void*, which requires forced type conversion to convert the void* pointer to the type we need.

4) When new fails to allocate memory, a bad_alloc exception is thrown. When malloc fails to allocate memory, NULL is returned.

2. Can I use malloc(1.2G) in a computer with 1G memory? Why? (Question from the second interview of Zhejiang Dahua in 2021)

Answer: It is possible to apply for 1.2G of memory.

Analysis: Before answering this question, you need to know the role and principle of malloc. Through the malloc function, an application can apply for a virtual address space from the program's virtual space. It has no direct relationship with the physical memory. What is obtained is the address in the virtual address space. The physical memory provided for the program to run is provided by the operating system.

3. The role of extern "C"

We can use the compiled function module of C in C++, and then we need to use extern "C". That is, extern "C" is added in the C++ file.

extern works in the linking stage (four major stages: preprocessing -- compilation -- assembly -- linking).

4. Which functions of strcat, strncat, strcmp, and strcpy will cause memory overflow? How to improve it? (2021 Zhejiang Dahua second interview question)

The strcpy function can cause a memory overflow.

The strcpy copy function is unsafe. It does not perform any checks, nor does it determine the copy size or whether there is enough memory at the destination address.

char *strcpychar *strDest,const char *strSrc)

The strncpy copy function, although it calculates the size of the copy, is also unsafe because it does not check the boundaries of the target.

strncpy(dest, src, sizeof(dest)); 

strncpy_s is safe

strcmp(str1,str2) is a comparison function. If str1=str2, it returns zero; if str1<str2, it returns a negative number; if str1>str2, it returns a positive number. (Compare strings)

The main function of strncat() is to append n characters to the end of a string.

char * strncat(char *dest, const char *src, size_t n);

The strcat() function is mainly used to concatenate two char types. For example:

char d[20]="Golden";
char s[20]="View";
strcat(d,s);
//打印d
printf("%s",d);

Output d is GoldenView (no space in the middle)

extend:

memcpy copy function, the difference between it and strcpy is that memcpy can copy any type of data, strcpy can only copy string type.

The memcpy function is used to copy the source memory (the memory area pointed to by src) to the destination memory (the memory area pointed to by dest); there is a size variable to control the number of bytes copied;

Function prototype:

void * memcpy ( void *dest, void *src, unsigned int count) ;

5. Usage of static (definition and purpose) (required)

1) Use static to modify local variables: change it to static storage mode (static data area), then this local variable will not be released after the function is executed, but will continue to remain in the memory.

2) Use static to modify global variables: make them valid only within this file, and other files cannot connect to or reference the variable.

3) Modify the function with static: This affects the connection method of the function, making the function only valid within the file and invisible to other files (this is very important in large projects, it avoids a lot of trouble and is very common). Such functions are also called static functions. The advantage of using static functions is that there is no need to worry about interference with functions of the same name in other files. In addition, it is also a protection mechanism for the function itself.

6. Usage of const (definition and purpose) (required)

const is mainly used to modify variables, function parameters and class member functions:

1) Use const to modify constants: they are initialized when defined and cannot be changed later.

2) Use const to modify the parameter: func(const int a){}; the parameter cannot be changed in the function

3) Use const to modify class member functions: This function can only perform read-only operations on member variables, that is, the const class member function cannot modify the value of the member variable.

Things modified by const are protected, which can prevent accidental changes and improve the robustness of the program.

Refer to the answer of a big guy:

Whenever I hear an interviewee say, "const means constant," I know I'm dealing with an amateur. Last year Dan Saks completely summarized all the uses of const in his article, so every reader of ESP (Translator: Embedded Systems Programming) should be very familiar with what const can and cannot do. If you have never read that article, just say that const means "read-only". Although this answer is not the complete answer, I accept it as the correct answer. If the candidate can answer this question correctly, I will ask him an additional question: What do the following declarations mean?

const int a;
int const a;
const int *a;
int * const a;
int const * a const;

The first two have the same function, a is a constant integer.

The third means that a is a pointer to a constant integer (that is, the integer is immutable, but the pointer is).

The fourth meaning is that a is a constant pointer pointing to an integer (that is, the integer pointed to by the pointer can be modified, but the pointer cannot be modified).

The last one means that a is a constant pointer to a constant integer (that is, the integer pointed to by the pointer is immutable, and the pointer is also immutable).

7. Function and usage of volatile

A variable defined as volatile means that the variable may be changed unexpectedly, so the compiler will not make assumptions about the value of the variable. To be precise, the optimizer must carefully re-read the value of the variable in memory each time it uses the variable, rather than using the copy stored in the register (although reading and writing registers is faster than reading and writing memory).

Those who cannot answer this question will not be hired. This is the most basic question that distinguishes C programmers from embedded system programmers. Embedded programmers often deal with hardware, interrupts, RTOS, etc., all of which require the use of volatile variables. Not understanding the content of volatile will bring disaster.

Volatile is used in the following situations:

1. Hardware registers of parallel devices (such as status registers)
2. Non-automatic variables accessed in an interrupt service subroutine
3. Variables shared by several tasks in a multithreaded application

8. The difference between const constants and #define (compilation stage, security, memory usage, etc.)

The constant defined by #define max 100 ; has no type (no type safety check, unexpected errors may occur), and an immediate value is given. The compiler only associates the defined constant value with the defined constant name. The macro variable defined by define is replaced in the preprocessing stage, and the constant must be copied and replaced wherever it is used in the program.

The constant defined with const int max = 255 ; has a type (type checking is performed at compile time) and a name, which is stored in the static area of ​​memory and has a value determined at compile time. During program execution, there is only one copy of a const variable, while a macro variable defined by #define has multiple copies, so the memory consumed by a macro definition during program execution is much larger than that of a const variable.

9. Scope of variables (global variables and local variables)

Global variables: defined outside of any function body, and available to all parts of the program (even code in other files). Global variables are not affected by scope (that is, the lifetime of a global variable is until the end of the program).

Local variables: appear in a scope, they are confined to a function. Local variables are often called automatic variables because they are automatically generated when entering the scope and automatically disappear when leaving the scope. The keyword auto can explicitly indicate this, but local variables are auto by default, so there is no need to declare them as auto.

A local variable can have the same name as a global variable. Within the scope of a local variable, the global variable becomes invalid and the value of the local variable is used.

10. sizeof and strlen (string, array)

1. If it is an array

#include<stdio.h>
int main()
{
    int a[5]={1,2,3,4,5};
    printf(“sizeof  数组名=%d\n”,sizeof(a));
    printf(“sizeof *数组名=%d\n”,sizeof(*a));
}

operation result

sizeof  数组名=20
sizeof *数组名=4

2. If it is a pointer, sizeof will only detect the pointer type, and pointers occupy 4 bytes of space (32-bit machine).

What is sizeof? It is an operator and a keyword, not a function, unlike strlen(), which is a function.

So what is the function of sizeof? Returns the number of bytes of memory occupied by an object or type. Do we perform operations on the data or pointers in sizeof()? Basically not. For example, sizeof(1+2.0) directly detects that the type is double, that is, sizeof(double) = 8. If it is a pointer, sizeof will only detect that it is a pointer type, and pointers occupy 4 bytes of space (32-bit machine).

char *p = "sadasdasd";
sizeof(p):4
sizeof(*p):1//指向一个char类型的

Unless strlen() is used, it is only valid for strings until '\0', and the count result does not include \0.

If you must use sizeof to get the size of the pointed content, you must use the array name, such as

char a[10];
sizeof(a):10  //检测到a是一个数组的类型。


Regarding strlen(), it is a function, and the inspection is relatively simple:

strlen “\n\t\tag\AAtang”

Answer: 11

11. Classic sizeof(struct) and sizeof(union) memory alignment

Memory alignment function:

1. Platform reasons (porting reasons): Not all hardware platforms can access any data at any address; some hardware platforms can only access certain types of data at certain addresses, otherwise a hardware exception will be thrown.

2. Performance reasons: Data structures (especially stacks) should be aligned on natural boundaries as much as possible. The reason is that in order to access unaligned memory, the processor needs to make two memory accesses; while aligned memory access only requires one access.

Three rules for struct memory alignment:

1. For each member of the structure, the offset of the first member is 0, and the current offset of the subsequent members must be an integer multiple of the current member type;

2. After all data members in the structure are aligned in memory, the structure itself needs to be aligned in memory again to ensure that the memory size occupied by the entire structure is the minimum integer multiple of the largest data member in the structure;

3. If the program contains the #pragma pack(n) precompilation directive, all members are aligned to n bytes (i.e., the offset is an integer multiple of n), and the current type and the largest type within the structure are no longer considered.

#pragma pack(1)
 
struct fun{
  int i;
  double d;
  char c;
};

sizeof(fun) = 13

struct CAT_s
{

    int ld;
    char Color;
    unsigned short Age;
    char *Name;
    void(*Jump)(void);
}Garfield;

1. Using 32-bit compilation, int occupies 4, char occupies 1, unsigned short occupies 2, char* occupies 4, and function pointer occupies 4. Since 32-bit compilation is 4-byte aligned, the structure occupies 16 bytes. (Note: the byte alignment is determined by the longest type of the structure. Here, int is the longest byte, so it is aligned to 4 bytes);

2. Using 64-bit compilation, int occupies 4, char occupies 1, unsigned short occupies 2, char* occupies 8, and function pointer occupies 8. Since it is a 64-bit compilation, it is 8-byte aligned (Note: the byte alignment is determined by the longest type of the structure. Here, the function pointer is the longest byte, so it is aligned to 8 bytes), so the structure occupies 24 bytes.

//64位
struct C 
{
 
 double t;   //8   1111 1111
 char b;  //1      1
 int a;   //4      0001111  
 short c;  //2     11000000
};  
 sizeof(C) = 24;  //注意:1 4 2 不能拼在一起

char is 1, and before int, the address offset must be a multiple of 4, so three bytes are added after char, that is, char occupies 4 bytes, then int occupies 4 bytes, and finally short, which only occupies 2 bytes, but the total offset must be a multiple of double, that is, a multiple of 8, so six bytes are added after short

Two major rules for union memory alignment:

1. Find the member that occupies the most bytes;

2. The number of bytes of the union must be a multiple of the bytes of the member that occupies the most bytes, and it must be able to accommodate the other members

//x64
typedef union {
    long i;
    int k[5];
    char c;
}D

To calculate the size of a union, we first need to find the member that takes up the most bytes. In this case, it is long, which takes up 8 bytes. Int k[5] is all int type, which still takes up 4 bytes. Then the number of bytes in the union must be a multiple of the number of bytes of the member that takes up the most bytes, and it must be able to accommodate the other members. In order to accommodate k (20 bytes), it must be a multiple of 8 and larger than 20 bytes, so it is 24 bytes.

Extension: Position domain (DJI written test question)

C language allows you to specify the length of memory occupied by a member in a structure in bits. This kind of member in bits is called a "bit segment" or "bit field". Bit segments can be used to store data with fewer bits. A bit segment must be stored in the same storage unit and cannot span two units. If the first unit space cannot accommodate the next bit segment, the space is not used and the bit segment is stored starting from the next unit.

1. Bit segment declaration is similar to structure

2. The members of the bit segment must be int, unsigned int, signed int

3. The member name of the bit segment is followed by a colon and a number

typedef struct_data{
   char m:3;
   char n:5;
   short s;
    
   union{
   int a;
   char b;
   };
    
   int h;
}_attribute_((packed)) data_t;

Answer 12

m and n together occupy exactly one byte of memory. Because the short type variable follows, a byte should be added before short s. So m and n actually occupy two bytes, and then short occupies two bytes, adding up to 4 bytes, and then the union occupies four bytes, a total of 8 bytes, and finally int h occupies four bytes, which is 12 bytes.

attribute ((packed)) cancels alignment

One of the major features of GNU C is the __attribute__ mechanism. __attribute__ can set function attributes (Function Attribute), variable attributes (Variable Attribute) and type attributes (Type Attribute).

The writing characteristics of __attribute__ are: there are two underscores before and after __attribute__, and it will be followed by a pair of parentheses, and the corresponding __attribute__ parameters are in the parentheses.

This is used for cross-platform communication. Memory alignment is different on different platforms. If you use structures for communication between platforms, there will be problems. For example, on the platform sending the message, the structure is 24 bytes, and on the platform receiving the message, the structure is 32 bytes (just a random example), then the values ​​corresponding to each variable will be incorrect.

The processor alignment methods of different frameworks may be different. If the alignment is not specified at this time, incorrect results will be produced.

12. Inline functions

In C language, if some functions are called frequently, functions are constantly pushed onto the stack, i.e., the function stack, which will cause a large amount of stack space or stack memory consumption. In order to solve this problem, the inline modifier is specially introduced to indicate inline functions.

On most machines, calling a function requires a lot of work: registers must be saved before the call and restored on return, actual parameters must be copied, and the program must also switch to a new location for execution. C++ supports inline functions, whose purpose is to improve the execution efficiency of functions. You can specify a function as an inline function by putting the keyword in front of the function definition (note that it is a definition, not a declaration). Inline functions are usually expanded "inline" at each call point in the program.

Inlining comes at the cost of code expansion (duplication), and only eliminates the overhead of function calls, thereby improving the execution efficiency of the function.

13. There are four memory areas. Which variables are stored in which area, on the heap or on the stack?

The text constant area, called .rodata, cannot be changed. Changing it will cause a segmentation fault.

int a0=1;
static int a1;
const static a2=0;
extern int a3;

void fun(void)
{
 int a4;
 volatile int a5;
 return;
}

a0: Global initialization variable; life cycle is the entire program execution period; scope is all files; storage location is the data segment.

a1: global static uninitialized variable; life cycle is the entire program execution period; scope is the current file; storage location is the BSS segment.

a2 : global static variable

a3: Global initialization variable; others are the same as a0.

a4: local variable; life cycle is during the execution of the fun function; scope is inside the fun function; storage location is the stack.

a5: local volatile variable;

14. When using 32-bit compilation, give a method to determine the big and small endianness of the machine used.

Union method judgment method: use the characteristics of the union structure that it is stored from the lowest address and only one member occupies memory at the same time. Big-endian storage is in line with reading habits. The union occupies the largest memory, which is different from the structure.

a and c share the same memory area, so changing c will inevitably affect the data of a

#include<stdio.h>

int main(){
  union w
  {
      int a;
      char b;
  }c;
  c.a = 1;
  if(c.b == 1)
   printf("小端存储\n");
  else
   printf("大端存储\n");
 return 0;
}

Pointer Methods

By converting the int type into a char single byte, p points to the starting byte (low byte) of a

#include <stdio.h>
int main ()
{
    int a = 1;
    char *p = (char *)&a;
    if(*p == 1)
    {
        printf("小端存储\n");
    }
    else
    {
        printf("大端存储\n");
    }
    return 0;
}

15. Use variable a to give the following definition

a) 一个整型数;
b)一个指向整型数的指针;
c)一个指向指针的指针,它指向的指针是指向一个整型数;
d)一个有10个整型的数组;
e)一个有10个指针的数组,该指针是指向一个整型数;
f)一个指向有10个整型数数组的指针;
g)一个指向函数的指针,该函数有一个整型参数并返回一个整型数;
h)一个有10个指针的数组,该指针指向一个函数,该函数有一个整型参数并返回一个整型数
答案:
a)int a
b)int *a;
c)int **a;
d)int a[10];
e)int *a [10];
f) int a[10], *p=a;
g)int (*a)(int)
h) int( *a[10])(int)

16. AND, NOT, XOR. Operator precedence

sum=a&b<<c+a^c;

Where a=3, b=5, c=4 (add first, shift, &, then XOR) Answer 4




Chapter 3 Network Programming

1. Differences between TCP and UDP

TCP---Transmission Control Protocol, provides a connection-oriented, reliable byte stream service. Before the client and server exchange data with each other, a TCP connection must be established between the two parties before data can be transmitted.

UDP---User Datagram Protocol, is a simple datagram-oriented transport layer protocol. UDP does not provide reliability, it just sends the datagrams passed by the application to the IP layer, but it cannot guarantee that they can reach the destination.

1) TCP is connection-oriented, UDP is connectionless

2) UDP program structure is relatively simple

3) TCP is byte stream oriented, UDP is datagram based

4) TCP ensures data correctness, but UDP may lose packets

5) TCP guarantees that data arrives in order, but UDP does not

2. Advantages and disadvantages of TCP and UDP

TCP advantages: reliable and stable

The reliability of TCP is reflected in the fact that before TCP transmits data, there will be three handshakes to establish a connection, and when data is transmitted, there are confirmation, window, retransmission, and congestion control mechanisms. After the data is transmitted, the connection will be disconnected to save system resources.

TCP disadvantages: slow, inefficient, occupies high system resources, and vulnerable to attacks

Before transmitting data, a connection must be established, which takes time. During data transmission, confirmation mechanisms, retransmission mechanisms, congestion mechanisms, etc. will consume a lot of time, and all transmission connections must be maintained on each device. However, each connection will occupy the system's CPU, memory and other hardware resources. Because TCP has a confirmation mechanism and a three-way handshake mechanism, these also make TCP easy to be exploited to implement DOS, DDOS, CC and other attacks.

UDP advantages: fast, slightly more secure than TCP

UDP does not have the various mechanisms that TCP has. It is a stateless transmission protocol, so the data transmission speed is very fast. Without these mechanisms of TCP, the chances of being exploited by attacks are less, but it cannot avoid being attacked.

UDP Disadvantages: Unreliable and unstable

Because UDP does not have these mechanisms of TCP, if the network quality is poor when transmitting data, it will easily cause packet loss and data loss.

3. TCP UDP applicable scenarios

TCP: Transmits information that requires signal integrity and quality.

UDP: When the network communication quality requirement is not high, but the network communication speed is required to be fast.

4. Why is TCP a reliable connection?

Because the data transmitted by TCP meets three major conditions: no loss, no duplication, and arrives in order.

5. What are the typical OSI network models?

6. Three handshakes, four waves

Three-way handshake

1. The TCP server process first creates a transmission control block TCB, ready to accept the connection request of the client process at any time. At this time, the server enters the LISTEN state;

2. The TCP client process also creates a transmission control block TCB first, and then sends a connection request message to the server. This is the same bit SYN=1 in the message header, and selects an initial sequence number seq=x. At this time, the TCP client process enters the SYN-SENT (synchronous sent state) state. TCP stipulates that the SYN segment (the segment with SYN=1) cannot carry data, but it needs to consume a sequence number.

3. After receiving the request message, if the TCP server agrees to connect, it will send a confirmation message. The confirmation message should contain ACK=1, SYN=1, and the confirmation number is ack=x+1. At the same time, it should also initialize a sequence number seq=y for itself. At this time, the TCP server process enters the SYN-RCVD (synchronous reception) state. This message cannot carry data, but it also consumes a sequence number.

4. After receiving the confirmation, the TCP client process also needs to give confirmation to the server. The confirmation message has ACK=1, ack=y+1, and its own sequence number seq=x+1. At this time, the TCP connection is established and the client enters the ESTABLISHED (connection established) state. TCP stipulates that the ACK segment can carry data, but if it does not carry data, the sequence number is not consumed.

5. When the server receives the confirmation from the client, it also enters the ESTABLISHED state, and then the two parties can start communicating.

Four waves

1. The client process sends a connection release message and stops sending data. The data message header is released, FIN=1, and its sequence number is seq=u (equal to the sequence number of the last byte of the previously transmitted data plus 1). At this time, the client enters the FIN-WAIT-1 (terminate wait 1) state. TCP stipulates that even if the FIN segment does not carry data, it consumes a sequence number.

2. The server receives the connection release message and sends a confirmation message, ACK=1, ack=u+1, and carries its own sequence number seq=v. At this time, the server enters the CLOSE-WAIT state. The TCP server notifies the high-level application process, and the client is released in the direction of the server. At this time, it is in a semi-closed state, that is, the client has no data to send, but if the server sends data, the client still has to accept it. This state will continue for a period of time, which is the duration of the entire CLOSE-WAIT state.

3. After the client receives the confirmation request from the server, the client enters the FIN-WAIT-2 (terminate wait 2) state, waiting for the server to send a connection release message (before this, it needs to receive the last data sent by the server).

4. After the server sends the last data, it sends a connection release message to the client, FIN=1, ack=u+1. Since it is in a semi-closed state, the server is likely to have sent some more data. Assuming that the sequence number at this time is seq=w, the server enters the LAST-ACK (last confirmation) state and waits for the client's confirmation.

5. After receiving the connection release message from the server, the client must send a confirmation, ACK=1, ack=w+1, and its own sequence number is seq=u+1. At this time, the client enters the TIME-WAIT state. Note that the TCP connection has not been released at this time. It must be 2* **MSL (maximum segment life) time, when the client cancels the corresponding TCB, before entering the CLOSED state.

6. As soon as the server receives the confirmation from the client, it immediately enters the CLOSED state. Similarly, after revoking the TCB, the TCP connection is terminated. It can be seen that the server terminates the TCP connection earlier than the client.

Chapter 4 Common Algorithms

Ten common sorting algorithms can be divided into two categories:

Non-linear time comparison sorting: The relative order of elements is determined by comparison. Since its time complexity cannot exceed O(nlogn), it is called non-linear time comparison sorting.

Linear time non-comparison sorting: It does not determine the relative order of elements through comparison. It can break through the time lower bound of comparison-based sorting and run in linear time, so it is called linear time non-comparison sorting.

Algorithm pros and cons evaluation terms

stability:

Stable: If a is originally before b, and a = b, a is still before b after sorting;

Unstable: If a is originally before b, and a = b, a may appear after b after sorting;

sort by:

Internal sorting: All sorting operations are completed in memory, occupying constant memory and no additional memory.

External sorting: Since the data is too large, it is placed on the disk, and sorting is performed through data transfer between the disk and the memory, which takes up additional memory.

the complexity:

Time complexity: The time it takes for an algorithm to execute.

Space complexity: The amount of memory required to run a program.



As for the principles and code implementation of various algorithms, they are too many and complex to be listed in this article. However, I recommend two introductory books: Aha! Algorithms and Data Structures. I will post the electronic version in the discussion group.

There are many sorting algorithms, but embedded systems don't require too many. If you know bubble sort, quick sort, and insertion sort, you can solve many problems. Difficult problems, such as dynamic programming problems and graph path problems, are rarely tested in embedded systems, and only pure software will test these. (The tests of large companies and unicorn companies are relatively difficult)


Chapter 5 Linux Operating System Topics

1. Components of the Linux kernel

The Linux kernel is mainly composed of five subsystems: process scheduling, memory management, virtual file system, network interface, and inter-process communication.

2. Components of Linux system

A Linux system generally has 4 main parts:

Kernel, shell, file system, and applications.

3. What are the communication methods between user space and kernel?

1) System call. The user space process enters the kernel space through the system call and accesses the specified kernel space data;

2) Driver. User space processes can use the encapsulated system call interface to access the driver device node to communicate with the driver running in kernel space;

3) Shared memory mmap. Call the interface in the code to implement address mapping between kernel space and user space. It is the first choice in projects with high real-time requirements, saving time and resources such as copying data, but the disadvantage is that it is difficult to control;

4) copy_to_user() and copy_from_user() are interfaces called in the driver to implement data copy operations between user space and kernel space. They are used in projects with low real-time requirements.

as well as:

procfs(/proc)
sysctl (/proc/sys)
sysfs(/sys)
netlink 套接口

4. The difference between system calls and ordinary function calls

System calls:

1. Using INT and IRET instructions, the kernel and application use different stacks, so there is a stack switch from user mode to kernel mode, so that privileged instructions can be used to control the device

2. Depends on the kernel, portability is not guaranteed

3. Switching between user space and kernel context is expensive

4. It is an entry point of the operating system

Normal function call:

1. Use CALL and RET instructions without stack switching during calling

2. Good platform portability

3. It is a procedure call, and the call overhead is small

4. Calling a normal function

5. The difference between kernel mode and user mode

Kernel state, the operating system runs in kernel state - running operating system programs

User mode, applications can only run in user mode - run user programs

When a process is executing the user's own code, it is in the user running state (user state). At this time, the privilege level is the lowest, which is level 3, which is the privilege level of ordinary user processes. Most programs that users directly face are running in user state. The Ring3 state cannot access the address space of Ring0, including code and data; when a process falls into the kernel code execution due to a system call, it is in the kernel running state (kernel state), and the privilege level is the highest, which is level 0. The executed kernel code will use the kernel stack of the current process, and each process has its own kernel stack.

6. The relationship between bootloader, kernel and root files

Boot sequence: bootloader->linux kernel->rootfile->app

Bootloader stands for bootloader, which is the first piece of code. It is mainly used to initialize the processor and peripherals, and then call the Linux kernel. After completing the system initialization, the Linux kernel needs to mount a file system as the root file system (RootFilesystem), then load the necessary kernel modules and start the application. (From a software perspective, an embedded Linux system can be divided into four parts: bootloader, Linux kernel, file system, and application.)

7. Two stages of Bootloader startup:

Stage 1: Assembly language

1) Basic hardware initialization (disable watchdog and interrupt, MMU (with operating system), CACHE. Configure system working clock)

2) Prepare RAM space for loading stage2

3) Copy the kernel image and file system image to RAM

4) Set the stack pointer sp

5) Jump to the entry point of stage2

Stage 2: C language

1) Initialize the hardware devices to be used in this stage (led uart, etc.)

2) Detect the system's memory map

3) Load the kernel image and file system image

4) Set the kernel startup parameters

The non-volatile memory widely used in embedded systems is usually Flash, and the Bootloader is located at the very front end of the memory, so the first program executed after the system is powered on or reset is the Bootloader.

8. Commands to check memory status under Linux

1)查看进程:top
2)查看内存:free
3)cat /proc/meminfo
4)vmstat

If a company server has many users, you can use the top command to see which colleague is using which command, what they are doing, and how much CPU is occupied.

9. The complete process of a program from start to end (four processes)

Pre-Processing, Compiling, Assembling, Linking

10. What are heap, stack, memory leak and memory overflow?

The stack is operated by the system and cannot be operated by the programmer.

So memory leak refers to the leakage of heap memory. Heap memory refers to memory allocated from the heap by the program, with any size (the size of the memory block can be determined during program execution), which must be explicitly released after use. Applications generally use malloc, new and other functions to allocate a block of memory from the heap. After use, the program must be responsible for calling free or delete to release the memory block, otherwise, this memory cannot be used again.

Memory overflow: The memory you request to allocate exceeds the amount the system can provide you, and the system cannot meet the demand, so an overflow occurs.

Memory out of bounds: A piece of memory is requested from the system, but when using the memory, it exceeds the requested range (a common example is memory out of bounds when using an array of a specific size)

Memory overflow is an inherent defect of C or C++ languages, which neither check array boundaries nor type-safety. As we all know, programs developed in C/C++ can directly access memory and registers because the target code is very close to the machine kernel. This feature greatly improves the performance of C/C++ language code. As long as the coding is reasonable, C/C++ applications will definitely be better than other high-level languages ​​in execution efficiency. However, C/C++ is also much more likely to cause memory overflow.

11. Causes and conditions of deadlock

The main causes of deadlock are:

(1) Due to insufficient system resources.

(2) The order in which the processes are run is inappropriate.

(3) Improper allocation of resources, etc.

If the system resources are sufficient and the resource requests of the processes can be met, the possibility of deadlock is very low. Otherwise, deadlock will occur due to competition for limited resources. Secondly, deadlock may also occur if the order and speed of process execution are different.

These four conditions are necessary conditions for deadlock. As long as deadlock occurs in the system, these conditions must be met. As long as one of the above conditions is not met, deadlock will not occur.

(1) Mutual exclusion condition: A resource can only be used by one process at a time.

(2) Request and hold condition: When a process is blocked due to requesting resources, it holds on to the resources it has obtained.

(3) Non-deprivation condition: Resources that a process has obtained cannot be forcibly deprived before they are fully used.

(4) Circular waiting condition: A circular waiting resource relationship is formed between several processes, with each process connected head to tail.

12. Hard links and soft links

The link operation actually assigns another name to a file that already exists in the system and can be used to access it. For this new file name, we can assign different access permissions to it to control information sharing and security issues. If the link points to a directory, users can use the link to directly enter the linked directory without typing a lot of path names. Moreover, even if we delete the link, the original directory will not be destroyed.

1>Hard link

A hard link can only reference files in the same file system. It refers to the physical index of the file in the file system (also called an inode). When you move or delete the original file, the hard link will not be destroyed because it refers to the physical data of the file rather than the location of the file in the file structure. Hard-linked files do not require users to have permission to access the original file, nor do they display the location of the original file, which helps to keep the file safe. If you delete a file that has a corresponding hard link, the file will still remain until all references to it are deleted.

2>Soft link (symbolic link)

A soft link is actually a newly created file that is used to point to another file (it is very similar to the shortcut file in Windows). A soft link generates a new file, but the function of this file is to point to a certain file. If you delete this soft link file, it means that you don't need this link and it has nothing to do with the original physical file. However, if you delete the original file, the corresponding soft link will be unavailable.

13. What is the difference between 32-bit and 64-bit in computers?

64-bit computing has two main advantages: it can perform integer operations in a wider range and it can support larger memory.

The size of virtual memory space under 64-bit operating system: The address space size is not 2^32, nor 2^64, but generally 2^48. Because the addressing space is not as large as 2^64, too large a space will only waste resources. Therefore, 64-bit Linux generally uses 48 bits to represent the virtual space address and 40 bits to identify the physical address.

14. The difference between interrupts and exceptions

Internal interrupt: A synchronous interrupt (exception) is an interrupt generated by an electrical signal inside the CPU. Its characteristic is that the interrupt is generated only after the currently executed instruction is completed. Since it is actively generated by the CPU, its execution point must be controllable.

External interrupt: Asynchronous interrupt is an interrupt caused by an electrical signal generated by the CPU's peripherals, and the time of its occurrence is unpredictable.

15. How does an interrupt occur and what is the interrupt handling process?

Request interrupt → respond to interrupt → turn off interrupt → save breakpoint → identify interrupt source → protect context → interrupt service subroutine → restore context → return from interrupt.

16. Linux operating system suspend, hibernate, and shutdown commands

The shutdown commands include halt, init 0, poweroff, shutdown -h, among which shutdown is the safest.

The restart commands include reboot, init 6, shutdown -r time

In the Linux command, reboot means restarting, and shutdown -r now means stopping immediately and then restarting.

You can search Baidu for specific available parameters.

17. Talk about a compilation optimization option under Linux:

Add: -o

18. In the case of data cache, the DMA data link is:

Peripherals-DMA-DDR-cache-CPU

19. Linux commands

1. Command to change file attributes: chmod (chmod 777 /etc/squid After running the command, the permissions of the squid folder (directory) are changed to 777 (readable, writable, and executable))

2. Command to find matching strings in files: grep

3. Find the current directory: pwd

4. Delete directory: rm -rf directory name

5. Delete file: rm filename

6. Create a directory (folder): mkdir

7. Create a file: touch

8. vi and vim file names can also be created

9. Decompression: tar -xzvf compressed package

Packaging: tar -cvzf directory (folder)

10. Check the port number corresponding to the process

1、先查看进程pid
ps -ef | grep 进程名

2、通过pid查看占用端口
netstat -nap | grep 进程pid

20. Hard real-time system and soft real-time system

Soft real-time systems:

Windows and Linux systems are usually soft real-time. Of course, there are patches that can make the kernel into a hard real-time system, but this is not done commercially.

Hard real-time systems:

There is a very high time requirement, and you must return within the specified time regardless of whether the work is completed or not.

Real-time systems such as VxWorks, uCOS, FreeRTOS, WinCE, RT-thread, etc.

21. MMU Basics

Modern operating systems generally use a virtual memory management mechanism, which requires the support of an MMU (Memory Management Unit). Some embedded processors do not have an MMU and cannot run operating systems that rely on virtual memory management.

In other words: operating systems can be divided into two categories, those that use MMU and those that do not.

The ones that use MMU are: Windows, MacOS, Linux, Android; the ones that don't use MMU are: FreeRTOS, VxWorks, UCOS...

Correspondingly, CPUs can also be divided into two categories, those with MMU and those without MMU.

The ones with MMU are: Cortex-A series, ARM9, ARM11 series;

The ones without MMU are: Cortex-M series... (STM32 is M series, without MMU, cannot run Linux, can only run some UCOS, FreeRTOS, etc.).

MMU is responsible for converting virtual addresses into physical addresses. The conversion process is relatively complicated and you can search it on Baidu.


Chapter 6 Common Interview Questions on MCU

1. ROM and RAM

I have explained this in another article, here is the link:

Difference between ROM and RAM


2. IO port working mode (people who have studied STM32 should be very familiar with it)

Pull-up input, pull-down input, push-pull output, open-drain output.


3. Please explain the similarities and differences between bus interfaces USRT, I2C, and USB

(serial/parallel, speed, full/half duplex, bus topology, etc.)

4. IIC protocol timing diagram

You must be able to draw it. I was asked about this during an interview and I gave a rough sketch.

The IIC protocol has two lines, one SCL clock line and one SDA data line. The figure shows the level status of the start signal and the end signal. After starting, because the IIC bus can be connected to many devices (no more than 8), a device address is sent first to select the device. The last bit of the device address represents whether it is writing or reading. After the device is selected, the register address is sent to represent the selection of a register, and then data transmission begins.

8-bit device address = 7-bit slave address + read/write address,

Add a direction bit to the address to indicate the direction of the next data transmission.

0 means the master device writes data to the slave device (write),

1 indicates that the master device reads data from the slave device (read)

Start signal: When SCL is at a high level, SDA jumps from a high level to a low level and starts transmitting data.

End signal: When SCL is at a high level, SDA jumps from a low level to a high level, ending data transmission.

Response signal: After receiving 8-bit data, the IC that receives data sends a specific low-level pulse to the IC that sends data, indicating that the data has been received. After the CPU sends a signal to the controlled unit, it waits for the controlled unit to send a response signal. After receiving the response signal, the CPU determines whether to continue to transmit the signal based on the actual situation. If no response signal is received, it is determined that the controlled unit has a fault.

During the data transmission of IIC signal, when SCL=1 high level, the data line SDA must remain stable, and no level jump is allowed. Only when the signal on the clock line is low level, the high or low level state of the data line is allowed to change. When SCL=1, any level change of the data line SDA will be regarded as the start signal or stop signal of the bus.

IIC I also have an article explaining, please see the link:

How many devices can be connected to the IIC bus at most?

5. The SP pointer of the MCU always points to

Top of stack


6. There are three types of signals in the IIC bus during data transmission:

They are: start signal, end signal and response signal.


7. FIQ interrupt vector entry address:

FIQ and IRQ are two different types of interrupts. In order to support these two different interrupts, ARM provides corresponding processor modes called FIQ and IRQ (ARM has 7 processing modes).

The interrupt vector address of FIQ is 0x0000001C, while that of IRQ is 0x00000018.

8. Four SPI modes, briefly describe one of them and draw a timing diagram

In chip data, polarity and phase are generally expressed as CPOL (Clock POLarity) and CPHA (Clock PHAse). Polarity and phase are combined into 4 operating modes.

SPI's four modes: The phase (CPHA) and polarity (CPOL) of SPI can be 0 or 1 respectively. The corresponding four combinations constitute the four modes of SPI.

Mode 0 CPOL=0, CPHA=0

Mode 1 CPOL=0, CPHA=1

Mode 2 CPOL=1, CPHA=0

Mode 3 CPOL=1, CPHA=1

Clock polarity CPOL: The level of the clock signal SCLK when the SPI is idle (1: high level when idle; 0: low level when idle) Clock phase CPHA: At which edge of SCLK does the SPI start sampling (0: the first edge; 1: the second edge)

The commonly used SPI modes for SD cards are mode 0 and mode 3. The similarity between these two modes is that they both sample and transmit data on the rising edge of the clock. A simple way to distinguish these two modes is to look at the clock level when idle. A low level is mode 0 and a high level is mode 3.

Please search Baidu for the specific communication process. This question was tested in DJI’s 2021 fall recruitment written test.

Chapter 7 Miscellaneous Interview Questions

1. Talk about the difference between the von Neumann and Harvard systems

Harvard architecture is a memory structure that separates program instruction storage from data storage. Currently, there are many central processing units and microcontrollers using Harvard architecture, including ARM9, ARM10, ARM11, and 51 single-chip microcomputers.

The von Neumann structure, also known as the Princeton structure, is a memory structure that combines program instruction memory and data memory.

2. Three characteristics of object-oriented programming

And the meaning of overloading. Overloading means that multiple functions with the same name are allowed to exist, but the parameter lists of these functions are different (perhaps the number of parameters is different, the parameter types are different, or both are different).

3. HTTP default port number

80

4. The default port of MySQL database in Linux is

3306

5. Tips on programming habits

In C language programming, the microcontroller platform generally has .c and .h files. If a person defines a variable in a .h file, what will be the consequences? (Discussing programming habits, I usually only declare functions in .h files and do not define variables; in addition, each module in programming will have corresponding .c and .h files, and the final overall program will define a comm.c and comm.h to call each module. I think this habit is okay)

If the if statement is an OR operation (|), when the first condition is met, will the second condition still be checked? If it is an OR operation, of course not, because 0|1=1, interrupting

end



A bite of Linux


Follow and reply【 1024 】 to get a large amount of Linux information


Collection of wonderful articles

Recommended articles

【Album】 ARM
【Album】 Fan Q&A
【Album】 All original
Album Getting started with Linux
Special Computer Network
Album Linux Driver

Latest articles about

 
EEWorld WeChat Subscription

 
EEWorld WeChat Service Number

 
AutoDevelopers

About Us Customer Service Contact Information Datasheet Sitemap LatestNews

Room 1530, Zhongguancun MOOC Times Building,Block B, 18 Zhongguancun Street, Haidian District,Beijing, China Tel:(010)82350740 Postcode:100190

Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号