UNIX advanced Environment programming (8) Process Environment (Process Environment)-Process startup and exit, memory layout, Environment Variable list, unixenvironment
Before learning about process control, we need to understand the running environment of a single process.
In this chapter, we will take a look at the following content:
- How is the main function called when the program is running;
- How is a command line parameter passed into a program;
- What is a typical memory layout;
- How to allocate memory;
- How the program uses environment variables;
- Various methods of program termination;
- How longjmp and setjmp functions work and interact with stacks;
- Process resource restrictions
1 main Function
Main function declaration:
int main (int argc, char *argv[]);
Parameter description:
- Argc: Number of command line parameters
- Argv: pointer to the parameter list Array
Before the main function is started:
- The C program is executed by the kernel and exec is called by the system;
- Run the specified start-up routine before calling the main function );
- The executable file considers this address as the startup address of the program, which is specified by the linker;
- The startup path obtains the parameter list and environment variables from the kernel, so that the main function can obtain these variables when it is called later.
2 Process Termination
There are a total of 8 methods to terminate the process, 5 normal termination and 3 abnormal termination.
5 normal termination:
Three types of exceptional termination:
The start-up routine is also the return address of the main function.
To obtain the address, you can:
exit (main(argc, argv));
Exit Function
Function declaration:
#include <stdlib.h>
void exit(int status);
void _Exit(int status);
#include <unistd.h>
void _exit(int status);
Function details:
- _ Exit and _ Exit are immediately returned to the kernel;
- The exit function cleans up the environment before returning to the kernel;
The return value of an integer is the same as that of the exit function:
exit(0);
return 0;
Atexit Function
Function Declaration
#include <stdlib.h>
int atexit(void (*func)(void));
Function details
- Each process can register 32 functions. These functions can be automatically called when the main function calls exit.
- The exit handler registered through atexit is called the exit handlers)
- The call order of these exit handles is the reverse order of registration.
- When the exit function calls the exit handle for the first time, all opened streams are closed.
- If the main program calls the exec functions, all registered exit handles will be cleared.
Procedure initiation and termination Flowchart
Example:
# Include "apue. h"
Static void my_exit1 (void );
Static void my_exit2 (void );
Int
Main (void)
{
If (atexit (my_exit2 )! = 0)
Err_sys ("can't register my_exit2 ");
If (atexit (my_exit1 )! = 0)
Err_sys ("can't register my_exit1 ");
If (atexit (my_exit1 )! = 0)
Err_sys ("can't register my_exit1 ");
Printf ("main is done \ n ");
Return (0 );
}
Static void
My_exit1 (void)
{
Printf ("first exit handler \ n ");
}
Static void
My_exit2 (void)
{
Printf ("second exit handler \ n ");
}
Execution result:
3. Command Line Parameter Example:
# Include "apue. h"
Int
Main (int argc, char * argv [])
{
Int I;
For (I = 0; I <argc; I ++)/* echo all command-line args */
Printf ("argv [% d]: % s \ n", I, argv [I]);
Exit (0 );
}
Execution result:
4. Environment Variable list
Each program accepts an Environment Variable list, which is an array directed by an array pointer. The array pointer type is:
extern char **environ;
For example, if the environment variable contains five strings (C-style strings), as shown in:
5 C program memory Layout
Shows the memory layout of typical C Programs:
Note:
- Text Segment to save the machine commands that the CPU will execute. Text segments can be shared. Therefore, when a program executes multiple times, the corresponding text segments only need to be copied in memory. The text segment is read-only to prevent program commands from being modified.
- Initialized data segment to save the global variables initialized in the Program (defined outside any function ). For example, int maxcount = 99; the global variable maxcount is saved in the initialized data segment.
- Uninitialized data segment, also known as BSS (block started by symbol), is initialized to 0 or null by the kernel before the program is executed .; For example, to define a global variable (defined outside any function), long sum [1000]; this variable is saved in uninitialized data segments.
- Stack: stores temporary variables and function-related information. When a function is called, the returned address and Caller information (such as register information) are stored in the stack. The called function allocates a part of space on the stack to save its temporary variables. This principle is also applied to recursive calls of functions. Each worker function calls itself, it will save the information of the current function, and then open up a new space on the stack to save the information of this function, and the previous function has no impact.
- Heap: the location of dynamic memory allocation. The heap is located in the middle of the uninitialized data segment and stack.
6. Memory Allocation (Memory Allocation)
There are three functions available for memory allocation:
- Malloc: Memory allocated to the specified number of bytes, not initialized.
- Calloc: Memory allocated to a specified number of objects. The memory is initialized to 0;
- Realloc: increase or decrease the previously allocated memory. Move the old memory content to the new larger memory block, and the excess memory is not initialized.
Function declaration:
#include <stdlib.h>
void *malloc(size_t size);
void *calloc(size_t nobj, size_t size);
void *realloc(void *ptr, size_t newsize);
void free(void* ptr);
Function details:
7. Environment Variable (Environment Variable)
String format of environment variables:
name=value
The kernel does not focus on environment variables. Only applications can use environment variables.
Use the getenv function to obtain the environment variable value.
#include <stdlib.h>
char* getenv(const char* name);
// Returns: pointer to value associated with name, NULL if not found
Function for modifying environment variables:
#include <stdlib.h>
int putenv(char* str);
int setenv(const char* name, const char* value, int rewrite);
int unsetenv(const char* name);
Function details:
- The putenv function is used to input a string in the form of name = value, which is added to the Environment Variable list. If the name already exists, delete the old definition first.
- The setenv function imports a name and a value. If the name already exists, the rewrite parameter determines whether to overwrite the old definition. If the rewrite is non-zero, the old definition is overwritten.
- The unsetenv function deletes the name definition. If the name does not exist, no error is returned.
It is interesting to modify the list of environment variables.
From the above C program memory layout, we can see that the Environment Variable list (save a set of pointers pointing to the environment variable string) is saved in the memory above the stack.
In this memory, it is easy to delete a string. We only need to find the pointer and delete the pointer and the string pointed to by the pointer.
However, it is much more difficult to add or modify an environment variable. Because the memory where the list of environment variables is located is usually at the top of the memory space of the process. below is the stack. Therefore, the memory space cannot be expanded up or down.
Therefore, the process of modifying the Environment Variable list is as follows:
- If we modify an existing name:
- If the size of the new value is smaller or equal to that of the existing value, the old value is overwritten;
- If the size of the new value is greater than the existing value, we must create a new memory space for the new value malloc and copy the new value to the memory, replace the pointer to the old value with the pointer to the new value.
- If we add an environment variable:
- First, we need to call malloc to allocate space for the string name = value and copy the string to the target memory;
- If this is the first time we add environment variables, we need to call malloc to allocate a new space, copy the old environment volume list to the new memory, and add the target environment variable after the list. Then we set environ to point to the new environment variable list.
- If this is not the first time we add an environment variable, we only need to allocate an environment variable space in realloc. The newly added environment variable is stored at the end of the list, and the list is still a null pointer.
Summary
This topic describes the process startup and exit, memory layout, Environment Variable list, and environment variable modification.
Next, we will learn four functions: setjmp, longjmp, getrlimit, and setrlimit.
References:
Advanced Programming in the UNIX Envinronment 3rd