Overview of C / C Development Technology under Unix / Linux
1. Profile of platform difference
Windows and UNIX are currently two mainstream operating system platforms, developers based on C / C often face the problem of transplant between these two platforms. As a developing system, UNIX has a lot of branches, including Sun's Solaris, IBM AIX, HP UNIX, SCO UNIX, Free BSD, Apple's Mac OS, and open source Linux. For these UNIX branch operating systems, there is a lot of differences, so developers have to transplant them against these different systems. The purpose of this article is to introduce the difference between the Windows platform and the UNIX platform, and briefly introduce the difference between the different UNIX branch operating systems, some precautions during the transplantation development process, and briefly introduce the general process developed under UNIX. And common development and commissioning tools.
With regard to the difference between the platform, the difference between the Windows platform and the UNIX platform, focusing on the differences in these two platforms in C / C development, and they will intend to describe the differences between some UNIX different branches.
1.1 Differences in language characteristics
The difference in language characteristics refers to different operating system platforms, and some subtle differences in C / C are realized, and these differences may result in some special hidden errors. And it may be a fatal error. Therefore, understanding the difference in language characteristics is very important for UNIX transplantation. If you consider multiple platform support, you must understand the difference in language characteristics under different platforms. From the beginning of development, these factors take into account these factors, so that minimize grafting process.
1.1.1 Differences in byte order
Byte sequence refers to the storage mode of the integer variable in memory. In a computer, data is stored in binary, including in memory and hard disks. The computer is made of 8-bit binary as a storage unit. In a 32-bit system, a integer storage requires four storage units. That is to say, a 32-bit integer partition is stored in the segment, and each segment stored position is the difference in byte order. The difference between byte order is derived from the difference in hardware platform, and the processor uses a different method when represented. Strict will, saying that there is a difference between the Wintel (Windows Intel) platform and other platforms when the byte differences under Windows and UNIX. Considering that the usual Windows is running under the Wintel platform, the UNIX system is generally under other hardware platforms (non-Intel), so it is also introduced in both Windows and UNIX as differences. Of course, Linux and Windows installed on the PC have the same byte representation, but when designing the network program, you should still consider the difference in byte order, because you don't know what the other party will be in the hardware platform. In order to clearly indicate the latter position of each segment, we use 16 credits to represent a value, the following table lists the cases in the unix system and Windows system in memory.
Hexadecimal representation 0x00004E20 Windows memory representation 20 4e 00 00 Unix memory represent 00 00 4e 20
As shown in the table, the storage mode in Windows and the 16 credit representation of the integer is the opposite, which is a low position in the predetermined storage order. The order of storage in UNIX is the same as the order of normal 16-based, referred to as a high position in the previous low. The problem brought about by this difference is mainly reflected in the following aspects: Ø Network communication
When network data transfer occurs between Windows and UNIX, when transmitting an integer data (such as a packet length), if the data in the memory is transmitted directly, then it is completely another data in the other party. This will cause problems. If Windows sends a 20000 (0x00004E20), the data received below UNIX will be understood to be 541982720 (0x204e0000), which is simply a hetero. Ø File storage and reading, comply with network transfer, if you write an integer in the file below, then open this file under UNIX, you will appear to have a similar problem with the above. This problem is mainly reflected in interoperability between different platforms. In the multi-platform development process, the data interaction between the two platforms is very common when the network application is developed, so this problem is very common. . The method of solving this problem is that the two sides of the interaction uses an identical data coding standard, which is to encode when the data is encoded when transmitting and stored, and the specific practice has several: 1. Digital conversion into a character transmission to interact 2. Negotiate an agreed byte sequence restores data according to the byte order of its own platform. Use other standard encoding methods, such as ASN1 encoding
Similar to this problem, the difference in 32-bit systems and 64-bit systems will also have such problems, and the solution is the same as the solution to this problem. In the 32-bit system and 64-bit system, long integer (long) is represented by 32-bit and 64 bits, so that the interaction between different systems will inevitably have a problem different. At present, most Windows systems are 32-bit systems, and many of UNIX are 64-bit, especially large servers, so this problem must be paid.
1.1.2
Variable scope difference
Under different systems, due to the difference in the compiler, the implementation mechanism of the variable scope is also different. Here is a simple comparison instructions for the CC in VC and Solaris under Windows. During the development of C , we often have such use: for (int i = 0; i {-------------------------------- ... For (int i = 0; i { ... I ii} ----------------------------------- - We divide the two scopes of I and II, where the scope II is included in the scope I. Under Windows, the scope of the variable I is the entire range of I, while the scope of the II below Solaris is only the range of II. In fact, the standard C syntax should be Solaris approach, but Microsoft is not implemented in this standard when it is realized, which has triggered this problem we discussed. Due to this difference, some subtle and concealed issues. Let's take a look at the following two ends of the code. A: for (int i = 0; i } B: for (int i = 0; i } Code A can be compiled normally in Windows, and below Solaris is not in the past, prompting the variable I in the second FOR loop is not defined. In contrast code B can be compiled normally under Solaris, and in Windows, the variable I repeat definition is prompted in the second FOR cycle. In general, we will write code according to the B method, and in Windows compilation is an error, then change to a form of A. In this way, there is no problem under Windows, and the program can also compile the past, but when you go to Solaris, there will be problems, this is, you have to get i's statement to all for loops. When i's statement gets the outside of the FOR cycle, the real problem is coming. First of all, this piece of code is no problem: c: int i = 0; if (cond) {... for (INT i = 0; i INT i = 0; --------------------------------------------- ------ CHAR STR1 [10]; Char Str2 [10]; STRCPY (STR1, "Hello"); ... for (i = 0; i <20; i ) {...} ... IF (COND) ------------------------------- { For (int i = 0; i <10; i ) ------------------ i {III IF (str1 [i] == 0) Break; II} ------------------ Memcpy (STR2, STR1, I); STR2 [i] = 0;} ------------------------------------------------------------------- ---------------------------------------- In the above code, in order to analyze convenient, we divide the entire code into three scope of I, II, and III. Where the scope II is the entire IF statement, the functionality implemented is equivalent to a STRCPY function. The content in II is good, of course, the later maintenance is added, of course, the actual situation is not as good as in our example, i's statement may be far from our IF statement, so add this code is not Know whether the I variable is declared. Moreover, this code does not return an error when compiling, whether it is Windows or Solaris (single II code in Solaris). In Windows, this code can run normally, no problem, because the code in II is completely written according to the habits under Windows. But under Solaris, this code will have an error in memory, although compilation can be passed normally, but the implementation is not the purpose of programmer expect. When Memcpy is executed, the I is actually the I, the value of 20, and the STR2 and STR1 are then the size of the STR1, so the reading and writing memory is happened. The programmer is expected that this I is the length of the STR1 string calculated by forbed and should be 5. To resolve such questions, you have to enhance programming specification and eliminate the generation of this error code. From the beginning, it is necessary to realize possible problems, thereby avoiding problems. 1.1.3 Initialization of global object In C , the system will automatically call the constructor when the object is initialized, so we are used to do some initialization work in the constructor, so that automatically automatically calls our initialization. Among them, some objects are static allocation global objects, which are objects declared in vitro, such as: CMYObject g_object; usually, when the program starts, the system will automatically call the object's constructor to initialize this global object. But in some systems (SCO UNIX), they don't want us to expect, maybe this is a bug that the compiler is implemented, but we can't ignore the existence of this problem. For this problem, we can solve it by explicitly creating objects, as follows: CMYObject * g_pObject = new cmyObject; This, the system will perform new cmyObject to assign space for the object, and perform call objects Function to initialize the object. If you don't want to use the pointer to reference the object (for security factors, you don't want a function to set this normally in the program run), then we can use another method, as follows: CMYObject & g_object = * (new cmyObject); It is also possible to achieve the work of object creation and initialization. Although there is no release operation for this object we allocated, the overall situation is only in this way, so don't worry about memory leaks. At the end of the program, the operating system automatically releases all the memory applied for the procedure, and of course this object is also included. 1.1.4 Grammatical examination difference Different operating systems have different compilers, different compilers are different from the degree of grammar requirements. The code that can be properly compiled under Windows, which may have syntax errors in UNIX. 1.1.2 It is a typical example. In addition, there are some differences in other aspects of grammar inspection. C is a very flexible language, syntax is free, but the degree of freedom in this different platform is also different. Windows VC, Solaris CC and Linux GCC implementation are good, but some other systems are not so flexible, and many ways to write will not pass them. Specific remembers are not too clear, and many of this situation is encountered under AIX and SCO UNIX. Therefore, it can only be gradually discovered and corrected during the transplantation. But as long as it guarantees the standard writing specification, this error should be generated less. There is such code: if (null == pvar) {...} This is a good habit of most platforms, which can avoid "==" to write "=" errors, can be able to compile Find. But under SCO UNIX, this way of writing will trigger a warning of the compiler. This example can simply explain the difference between the different compilers. 1.2 Differences in the operating system characteristics There are some system restrictions, such as the limit of opening the file handle, the restriction of the Socket wait for the queue, the limitations of the process, and thread stack size, so in the development process, must be considered The impact of these limiting factors on the program. Of course, some restricted parameters can be adjusted appropriate, which requires declaration when the release program is released. In addition, the fault tolerance of the operating system also has an impact on the program. The discussion is discussed below. 1.2.1 File Descriptor Limit The file descriptor was originally a concept under UNIX. In the UNIX system, with a file descriptor to represent files, open Socket connections, etc., similar to the concept of Handle under Windows. The file descriptor is a system resource, and the system is limited to the number of file descriptors assigned by each process. Take Solaris as an example. By default, each process can open the file descriptor to 1024, the hard limit of the system is 8192 (the specific value and version is related), that is, it can be adjusted to 8192. Use ulimit commands under UNIX systems to get these restrictions of the system. In general, this is enough, but there is an exception, in the 32 Solaris program, using the standard input output function (STDIO) to perform file operation, the maximum file descriptor cannot exceed 256. For example, use FOpen to open files, go out of the three file descriptors (stdin, stdout, and stderr) occupied by the system, and only 253 files can only be opened at the same time. If you use the Open function to open the file, there is no limit, but it is not possible to operate using those functions in STDIO, which is a decrease in the versatility and flexibility of the program. This is because in the STDIO's File structure, use a unsigned char to represent a file descriptor, so only 0 to 255 can be represented. In the development of the network program, each network connection also takes up a file descriptor. If the program has opened a lot of socket connections (typical examples, the connection pool technology is used), then the program may not be opened when the program is running. . To solve this problem, you can use a few ways: 1. Upgrade to 64-bit system or use 64-bit compiler 2. Use the function to operate file 3 in SYS / IO.H. With file pool technology, some file descriptors (between 3 to 255) are reserved, using the Freopen function to reuse these descriptors. As for which method or whether to consider this problem in the system, it is necessary to depend on the specific situation, and those who do not affected by this restriction can not consider this problem. 1.2.2 limitations of processes and threads The general operating system has restrictions on the number of resources that can be used by each process and threads, such as the number of threads that can be created, the number of file descripts, process and thread stack size, etc. . In response to these problems, what is the first to analyze and consider your system, will not receive the impact of these restrictions, if the demand is greater than the system limit, can be solved by appropriate adjustment system parameters, if it is still not resolved It has to consider the use of multi-process way to solve. For the limitations of the stack space size of the process and threads, it is mainly the problem of thread stack space. The general system has the default thread stack space size, and the default values of different super system may be different. Under normal circumstances, these have no effect on the program, but when the hierarchy of the program is more complicated, excessive local variables are used, which may have an impact on the program, causing stack space overflow, this is a more serious problem . You cannot solve this problem by adjusting system parameters, but can specify the size of the stack space of the thread in the program by the corresponding function. However, the value of the specific adjustment should be suitable, not the bigger better. Because the thread's stack is too large, it will affect the number of creative threads. Although it is far from reaching the limit of the system multi-thread number, it may fail because the system resource has caused the distribution of memory failed. Linux thread is achieved by a process, actually a fake thread. If the program is only running under Linux, you can consider using multi-process techniques instead of multithreading because multi-threads under Linux do not bring multi-threaded advantage than multi-process. 1.2.3 Restriction of network communication capabilities For network programming, performance is the most important factor. In order to improve the performance of network communication, the system provides a lot of assistive technologies, where the queue is one of them. For programs, only one network connection request can be handled at a point in time, and if there is a number of network connection requests at the same time, there will be many requests fail. In order to solve this problem, the operating system provides a wait for queue technology, which is to process the connection request to the system's waiting queue so that the success rate of the network connection can be improved. Waiting for the creation of the queue also needs to consume system resources, so the system has restrictions on the size of the wait queue, and the program can be set by the function to the size of the queue, but cannot exceed the hard limits of the system. The size of the maximum wait queue of several operating systems is listed below: Operating system Maximum waiting queue Windows 2000 Server 200 Windows XP Home 5 Solaris E250 128 On the table, only the waiting queue parameters of several operating systems are simply listed, and other system temporary is listed. If you are interested, you can test it yourself. So this problem is related to the specific system environment, but we can do some work on the basis of the system connection pool and use the connection buffer pool technology. After accepting the network connection request, put it to a buffer pool before submitting the process. This can accept more connection requests waiting to be processed, enhance the connection success rate of the system to a certain extent. However, unlike the system's waiting queue, this is the waiting queue implemented by software, and the connection pool provided by the system is solved from the operating system level, closer to the hardware level, so efficiency will definitely be different. In the face of such problems, first, it is still possible to adjust the size of the system connection pool, and then use other auxiliary means. 1.2.4 Effect of fault tolerance With the C / C development program, the buffer overflows are very common, but the processing capabilities of these errors that have occurred during the system are running. In general, the Windows system has the strongest fault, especially the Debug version of the program, and the system has added some protection mechanisms to ensure that some small errors will be able to run normally. The UNIX platform requires strict, some systems do not have a little sand, there is a downtime, which is related to the operating system's memory distribution mechanism. When the Windows platform program is allocated, some bytes generally are generally used for alignment. If the buffer overflows not too much, it will not return to the value of other variables in the memory, so the program can also function properly. But this protection mechanism will bring more system overhead. This is one of the main reasons why Windows program ported to UNIX's stability reduction, and why the Windows system consumes so many system resources. To solve such problems, you have to perform more stringent tests and code checks. At the same time, with the help of related test tools, find out the potential problems hidden in the system, and cannot let go of any possible errors, especially the warning information found during the compilation process. Of course, these tasks should be made before transplantation, and the efforts should be increased after transplantation. 1.3 Graphical user interface Windows and UNIX graphics models are great, this is the biggest difference in UNIX and Windows program development. UNIX uses the X Window System GUI, while Windows uses GDI. Although there is no simple correspond to the X API and GDI APIs. Under Windows, you can easily develop programs for graphical user interfaces through the MFC and other class libraries, while Unix is more troublesome, lacking which newly obtained development tools. The GUI program development under UNIX is a more complex process, which is not described in detail here. If you want to develop the development of the GUI program under UNIX, you can find the relevant documentation separately. 1.4 concurrent processing Concurrency processing includes multi-process and multi-threaded concepts, Windows and UNIX concurrent processing differences are relatively large, but basically find a set of corresponding functions to implement similar functions. Under Windows, create processes and threads can be done by calling the Windows API, or by calling the concurrent processing class library provided by the MFC. Creating a process under UNIX usually uses a Fork function, which is different from the multi-process concept below Windows, which is equivalent to creating a copy at the current location; and most of Windows creates a new process. Multi-threaded operation under UNIX, through a set of thread functions, usually we use POSIX's PTHREAD thread library to create threads, but in different UNIX branch systems, we include its own local thread library. As in Solaris, the local line library is a set of functions starting with THR_, while POSIX's thread function is generally pthread_ start. Although there are two different thread libraries, we choose, but under a particular system, their implementation is the same, and basically can find corresponding functions. For the portability of the program, it is recommended to use POSIX thread libraries. This is the thread library supported by most UNIX systems, but the functions implemented under different systems may differ, may just implement a subset of this function library. Under some UNIX systems, the thread library is not implemented, such as SCO UNIX, the system only provides a multi-process development method. However, if we can implement the thread library provided by third parties in order to implement the unity of program code. Here is a thread library called FSU-Threads for us to choose. This thread library implements the thread function defined in POSIX, and is open source, which can support SunOS 4.1.x, Solaris 2.x, SCO UNIX, FreeBSD, Linux and other systems. In addition, there are Zthreads thread libraries. In Windows's thread library, synchronous objects such as mutex, events (event), semaphore are implemented, which are used to implement synchronization between threads. Below UNIX, thread synchronization primarily uses a mutex and conditional variable (COND), where conditional variables can implement events and signals. In addition, POSIX also defines a set of semaphore function, which is different from the thread function, a set of functions starting with SEM_ (POSIX 1003.1B Semaphores). But this set of functions don't want POSIX thread function support, such as the POSIX signal function function is not supported on AIX, but there is another set of functions in the AIX system to implement Systemv SemaphoRes. In many UNIX systems, it supports POSIX signals and SYSTEMV signals, and there is a set of local functions under Solaris to implement semaphore. The main functions for concurrent processing in the UNIX system are listed below. Create a process fork process POSIX threads library pthread_create creates a thread pthread_attr_init letter initialize a thread attributes object pthread_attr_destroy release a thread attributes object pthread_exit thread pthread_join terminate the current call calling thread is suspended until the end of the target thread scheduling policy and set the thread pthread_setschedparam pthread_getschedparam get the thread priority and scheduling policy priority pthread_sigmask change / check signal mask pthread_kill calling thread to another thread pthread_self transmission signal return current thread ID pthead_mutex_init initializing a mutex pthread_mutexattr_init mutex attribute object initialized to pthread_mutex_lock A mutex lock, if the mutex has been locked by other threads, call the thread hang until the other thread releases pthread_mutex_unlock releases the mutex (unlocked) Ptherad_Mutex_DESTROY Destroyed a mutex PTHREAD_CONIT initializes a condition variable Pthread_Condattr_init initialization one Conditional variable attribute object pthread_cond_wait Block in a condition variable PTHREAD_SIGNAL Release the next thread in the conditional variable PTHREAD_COND_BORADCAST release all threads on this condition variable block PTHREAD_ COND_DESTROY destroys a condition variable PTHREAD_CANCEL request to end a thread Solaris Local Gallery THR_CREATE Create a new thread thr_exit termination call thr_join pending the current call thread, Until the target thread end thr_yield uses the current thread with the current thread THR_SUSPEND hangs a specified thread THR_CONTINUE to restore a pending thread thr_setPrio Modify thread priority THR_SIGSETMASK change / check the signal mask of the calling thread THR_KILL sends a signal to another thread thr_self Returns the ID THR_MAIN tag of the current thread to initialize a mutex THR_MUTEX_LOCK to lock a mutex, if the muteness has been locked, the call thread hangs until other thread releases thr_mutex_unlock release mutex (unlock) thr_mutex_destroy destroy a strip mutex thr_cond_init initialize a condition variable thr_cond_wait blocked on a condition variable thr_cond_signal next to lift a thread to lift the blocking thr_cond_boradcast condition variable on the condition variable in all threads Block Thr_Cond_Destroy Destroy any condition Variable RWLOCK_INIT initializes a read-write lock RW_RDLOCK to get a read-write lock read lock RW_WRLOCK Write a read-write lock RW_UNLOCK unlocks a read and write lock POSIX semantic signal SEM_INIT initializes a signal amount SEM_DESTROY destroys a seminated SEM_WAIT Wait to get a semaphore , The current thread is blocked, supports some thread release signal SEM_TRYWAIT attempts to obtain a semaphore, the value of the semaphore is reduced by 1, if the current signal value bit 0, the return failed SEM_POST releases a semapic SEM_GETVALUE to get the specified semaphore Value System V Semic SemCTL performs a series of control Semget for a series of control Semget to create a signal amount, and the ID SEMOP of the signal is subjected to the signal of Solaris. Closer to the SMA_INIT in the operating system, the SEMA_INIT initializes a signal (selection) SEMA_DESTROY destroys a signal light SEMA_P execution signal light SEMA_P_SIG is similar to SEMA_P, when it is blocked, if the thread receives one Signal, function Exit SEMA_TRYP Attempts to execute the SEMA_V execution signal of the signal light SEMA_V Perform signal lights For convenience, I have already encapsulated the above commonly used functions in the process of development, compatible with Windows and a variety of common Unix systems, and There are also many code resources available on the Internet available. If you are interested, you can ask me. 1.5 network communication Socket (Chinese translation: socket) initially appeared on UNIX and quickly became one of the most popular network programming interfaces on UNIX. Later, Microsoft introduced it into Windows and achieved it, so starting from Windows 95, WinNT4, the system has built-in Winsock1.1, and later to Windows 98, Windows2000, its built-in Winsock DLL update to Winsock 2.2. The socket function under Windows is mostly similar to the socket function under Unix. The function name is similar. There are only some subtle differences, the meaning of certain parameters is different, and the attribute control of Socket is not the same. Windows also encapsulates the Socket function below, and a series of related classes are available to simplify the complexity of network programming. UNIX itself does not have these class libraries, but we have also accumulated many experience and resources in this area. We have a set of ready-made classes to encapsulate Windows and UNIX's Socket function, and the upper layer only requires simple calls, do not care about the difference in the underlying. Moreover, this set of libraries can also support multiple platforms at the same time, which is very portable. For Socket development, please refer to some relevant information to introduce Socket programming. 2. Basic development process Developing programs under UNIX, unlike the development of Windows, in addition to the difference in the program level described above, the development environment has great differences. Below Windows, mostly use integrated development environments, such as MS Visual C , Borland C Builder, etc. In UNIX, there is also an integrated development environment, such as Sunshop, KDevelop under Linux, but because many UNIX development is transplanted, now Windows is basically completed, and then under porting to UNIX, the amount of code is not too big. So often use the Makefile method without using the IDE development environment to recreate the project. The main content of this chapter is to introduce the basic processes developed under UNIX and some development commissioning tools. 2.1 Code writing For transplant projects, basic code is completed under Windows, just need to pass to UNIX, then organize the source code directory below Unix. For editing to the UNIX code, you can use the VI tool under UNIX to complete, or you can open the file under UNIX by UltraEdit. VI is the most commonly used text editor under UNIX, and some basic usage of VI will be described later. One thing is worth noting that the carriagebox in Windows contains two characters '/ n' and '/ r', and the carriage return inside the text under UNIX contains only one character '/ n'. In this way, if you do not choose the correct way, you should use the binary method using the text method, or you should use the use of text methods to use in binary mode, then there is a problem under UNIX, and the open text is A '^ m' character will appear in the end of a row. Can be solved by the matching replacement function of VI (later will be described later) or re-according to the correct way. 2.2 Compile 2.2.1 Simple compilation For simple programs, such as only a few source files, you can use the compiler to compile, or write several compile commands in a script file, and implement the engineering and connection of the project by performing the script file. For example, only one Hello.cpp file project, can compile the following command: cc -o hello hello.cpp where the CC is a compiler, and the different systems may have different compilers. In general, the C compiler under most UNIX systems is called CC, and the C compiler is called CC. The C compiler under Linux is GCC, the C compiler is G . The -o parameter is used to specify the name of the target of the output, which is the name of the program after compiling. In this case, compile and connect one step. For programs that are slightly responsible, include multiple source files, you can write a compilation script, which is equivalent to batch under Windows. As follows: Engineering contains hello.cpp, other.cpp, we can use the following scripts to implement engineering compilation. Cc -c hello.cpp cc -c func.cpp cc -c otcccpp cc -o hello hello.cpp cc -o hello hello.o func.o Other.o multiple files, execute the compilation and connection, first compile the source file one by one. Then there is a link to form the final executable. Parameters -C is a statement that only compiles. 2.2.2 Using Makefile When the project reaches a certain scale, 2.2.1 The practice is obviously not satisfied. If you do it, you will bring a lot of workload, and it is very easy to make mistakes. This is what we use Makefile to help us complete the engineering compilation. The Makefile file is equivalent to a project file, which describes the source code in the project, an additional library file and its path, additional header files have been compiled, compile parameters, etc. Turn into Makefile for engineering compilation through the make command. When executing the make command is, search the name "makefile" or "makefile" in the current directory, as the currently compiled engineering file, you can also specify another project file, such as make -f mymakefile. A simple Makefile file is as follows: #makefile for Linux (redhat) Macro definition # 目 目 程序 Name Bin_Name = Demo # 编 编 器 and compile parameters cc = GCC CXX = G cxxflags = -g document list # 代 列 list SRCS = / demo.cpp / func.cpp # target file list, generate OBJS = $ {srcs: .cpp = .o} through the source code list. # 依赖 关 #depends all: $ {bin_name} .depends: $ {srcs} # rely on rules @echo create, depyle, please wait ... Dependency $ {Cxx} -m $ {srcs}> .depends execute the command -include .depends #%. o:%. CPP # @Echo compling file: $? Please wait ... # $ {Cxx} $ {cxflags} -c $? $ {Bin_name}: $ {@ @ please wait ... $ {cxx} -o $ @ $ {objs} clean: RM -F $ {bin_name} $ {objs} * pure .depends In the makefile file, it is generally divided into three parts: "Macro Definition", "File List", and "Dependencies". Macro definitions Define some macros in which Makefile can be used, and after a macro, the rear portion of the makefile can be used to obtain the value of the macro by macro. Like compiler, compile parameters, etc., usually define a macro, and then modify the compiler type and compile parameters by modifying the value of the macro. In more complex Makefile, the macro definition will also contain dependencies, which requires an increased library file path and header file path, predefined macro in the program. In fact, the list of documents is also a macro, just considering his importance, so it is described separately as a part. This macro will be used in the rear dependent relationship. The file list defines all source files included in the project and the target files generated after these source files compile. The target file can be generated through the source file list. Above we use $ {srcs: .cpp = .o} to generate a list of target files, meaning that all extensions in the source file are ".cpp" ".o" .o. The dependency part is the key to the Makefile file, which defines multiple dependencies. Each dependency further includes a dependency rule and a set of executed commands. Relying on rules consists of objectives and dependent objects, that is, this goal relies on the specified dependent object. When executing Make, if the update time of the discovery of the target does not exist or the target's dependent object is more than the target, the command in the dependency is performed to complete compilation of the target. Multiple goals can be defined in Makefile, each target corresponding to a dependency and a set of commands. When performing make, you can perform the target to be compiled. If Make Clean means checking the execution of the target Clean. All is a default target, when executing MAKE does not add parameters, will default to check the goal of executing ALL. Makefile can specify dependency objects and commands to be executed for the All target. Makefile, you can also specify only dependencies, do not specify the command to be executed, most of which is used for dependent objects and a definition target. Make In checking dependencies, if the dependent object is also a target, you will first check this goal, see if you need to recompile this goal, and then execute the following command below. In order to realize the compilation of the source file, we need to define dependencies between source files and target files in dependencies, and then create a dependency between the programs and these target files. This allows you to achieve compilation of the entire project. In this makefile, two methods that define this dependency are included. One is the "-m" command of the compiler to form a dependency file, and then the contents of this file include in the current dependency, The other is to form a dependency on the mapping relationship of the source file and the target file by matching the replacement. The red font part and the blue font part represent these two practices, respectively. The "-m" parameter is the GCC / G compiler unique, other compilers generally do not have this parameter, the second approach should be used. In different systems, Makefile's grammar will have some subtle differences. At the time of multi-platform transplantation, you should pay attention to this problem, and write different Makefiles for different systems. 2.2.3 Automake and AutoConf Although the basic structure of the makefile is very simple, it can change many different patterns to properly use these rules. But because of this, many have just started to learn to write makefile, I feel that there is no specification that can be followed. Everyone writes a lot, I don't know where to start, and often restrictions on their own development environment, as long as environmental parameters Different or path changes, may make Makefile to follow the modifications. Although there are some standards and specifications for GNU Makefile Conventions to write Makefile when designing GNU program design, it is very long and complex, and often makes some adjustments, to reduce program developers to maintain Makefile's burden Therefore, Automake appeared. Program designers only need to write some pre-defined macros (Macro), which will generate a Makefile.in file that can be used by AutoConf after submitting the Automake process. Re-cooperates the automatic cultivation setting file Configure that uses AutoConf to generate a Makeifle that meets the GNU Makefile formula. The basic usage of Automake is first to search for the current directory with AutoScan, then form a configure.scan file, then use the configure.scan file as blue, form a configure.in file, which is the final file. Then use the ACLOCAL to process the local macro and use AutoConf to generate a Configure script file. The Configure script file is used to form the final makefile. After compiling a makefile.am, define some macros needed by Automake, including the list of source files, and the like. Execute Automake to form a Makefile.in file. In this way, the preparations needed are basically completed. When compiling, by executing the configure script, the makefile file is automatically generated, and then executes Make is OK. For details on Automake, please check the reference. 2.3 Run and debugging with Windows Unexpected, UNIX The following file can only be executed, unlike the extension as Windows. So the execution program under UNIX has no extension, and any file can be run directly as long as it gives an execution permission. You can add executable permissions to a file via CHMOD X. The target file formed after compiling, usually has permissions, so you can do it directly. 2.3.1 Set up a running environment For simple programs, don't set up what to run, you can run them directly. For programs responsible, you may need to set some running environments if you may perform programs and need shared library files. Setting the running environment is mainly to set the path to the shared library. Shared libraries under UNIX, equivalent to the dynamic library (DLL file) under Windows, is a file with .so is an extension. The shared inventory of the system is placed under / usr / lib, and the program will automatically go to the required shared library when running. For the shared library developed by the user, it is generally not placed under the / usr / lib directory, but below the user's program directory. A more complex program whose directory structure is clear, not to put all the files under a directory. The following is a typical directory structure: MainPath Program Main Directory MAINPATH / BIN Executes Program Directory MAINPATH / LIB shared library directory, you need to set the program's running environment, specify the library file directory. Setting the running environment is actually set a number of environment variables before running the program, where the shared library is one of them, or you can set other environment variables required by some programs. Unix uses ld_library_path below to represent the path of the user sharing library. Set the environment variable, you can run the program. There is a more convenient way to write execution scripts. The script below Unix is equivalent to the batch file under Windows, which is to perform a series of commands. In essence, the script file is a text file, and an executable permissions are added after the editing is complete. The terminal window under UNIX is based on the shell. In UNIX, you will most often use the Bourne Shell and C shell, and the system uses the Bourne Shell by default. Different shells have different programming languages, that is to say to write a language of the shell script, used to implement some more advanced features. In the script, you can specify the language used in this script. For more information on Shell Programming, please refer to the reference. In general, the Bourne Shell script file is in .sh as the extension, the c shell script file is extension in .csh as the extension. Here we take Bourne Shell as an example. In a typical program directory, there are three scripts: perform scripts (run.sh), stop process scripts (kill.sh), and set an environment script (STenv.sh). Script files are generally placed under the primary directory of the program, and enter the primary directory can be implemented directly through these scripts. The following is simple to list the contents of these scripts. Stenv.sh: #! / bin / sh path = `pwd` ld_library_path = $ path / lib: $ library_path export ld_library_path run.sh: #! / bin / sh path =` pwd` ld_library_path = $ PATH / LIB: $ LD_LIBRARY_PATH Export ld_library_path cd bin ./demo cd .. kill.sh: #! / usr / bin / sh for sid in `ps - e | grep demo | awk {'print $ 1'}` do kill $ sid done is worth noting Yes, the outer casing is actually a process, and a new process will be created after running the script. The environment variable relies on the process, that is, the environment variable set in the script will disappear after the script is completed, and does not return to the housing process and other processes. That is to say, our STenv.sh is equivalent to any effect. However, the environment variables set during the execution of the script can be reserved by another way of implementing the method, ie ". SetENV.SH". In fact, add a '.' And spaces in front of the execution command. Such an environment variable set in this script will perform the outer casing process of this script in the scope and affect all processes running under this housing under this housing. 2.3.2 Using the Debug Tool for debugging, it is the most important part of the program development, and finds the bug in the program by debugging. The program debugging tool below Unix has a lot of debugging tools, including debugging tools and character interfaces in an IDE environment. Here we mainly introduce the debugging tools for the character interface. Commonly used adjustment is that tools are DBX, and there are most UNIX systems. In Linux, the debugging tool is GDB, the function is similar to DBX. Similar to Windows, to run the program in debugging, you must compile the program in debug. The compilation below Unix is generally compiled with the DEBUG mode through the -g parameter, so that the source code is included in the compiled target file. The following is a GDB as an example, introducing the basic method of debugging under UNIX. 1) Under debugging mode running the program in the directory where the program is located, execute the GDB, and enter the GDB debug interface with the program name as a parameter. Such as: GDB Demo 2) View the source file, set the breakpoint in GDB, use the list command to view the contents of the file where the main function is located. By default, 10 line contents are displayed at a time, and the LIST can be executed again to display the rest of the 10 lines. Make sure you set the breakpoint on which row, then use the BREAK command to make a breakpoint setting. Such as: BREAK 10 indicates a breakpoint on page 10. The BREAK command can also specify a file to set the breakpoint (if not the file where the master function is located), such as: BREAK FUNC.CPP: 10 indicates a breakpoint on the 10th line of Func.cpp. In addition to setting breakpoints on a specific line, you can set a breakpoint on a function, as long as the line number is replaced with a function name. The CLEAR command is used to clear the current line breakpoint, and the delete command can delete all set breakpoints. 3) After running the program sets, you can run the program through the run command under GDB. If the program needs to do what parameters, place it directly after the Run command, such as Run -start Where -start is a program that allows the required parameters. 4) Distance program analysis When the program executes to breakpoint, it will be waiting to wait for the user to process. This is the current operational state of the program that can be viewed by some commands, including: Print print variable value, only You need to use the variable name to make a command parameter, you can display the value of the current call stack set variable to change the variable, which may affect the results of the program. 5) After the single-step debug is completed, you can continue to execute The program, the next command is used to perform a row code, and the step command is used to track the upcoming function. The Continue command can continue to run the current program until the next breakpoint is encountered. In the above process, briefly introduce some debugging of how to use GDB. All commands in GDB can be represented by shortcomings, as long as the number of alphabets that can be distinguished, such as a simple input n to indicate the next command. In addition to the commands described above, there are many useful commands. Attach and Detach Commands, can help the GDB to a process in the case where the program is run, debug, restore normal programs after debugging, launching GDB does not affect the program; the PWD command can display the current working directory The CD command can change the current working directory; the thread command can view the current thread ID. There are still many other commands that can be used to get detailed help through the Help command. In addition to DBX and GDB, there are still many debugging tools below UNIX. For more information, please see the reference. 2.3.3 Core Dump For UNIX developers, Core Dump is more familiar. Next, Core Dump is the most serious manifestation of program bugs. Core Dump is also called core dump. When the program runs an exception during the run, the system will store the program's current memory status in a core file, it is called Core Dump. Since the core file records the case of the program run, you can analyze the cause of the error via the Core file. Using the GDB / DBX Run program name Core can restore the program to which time that the program has an error, you can see which row code is executing, when calling what function is called. This is, you can make more detailed analysis by other commands of the debug tool. Personally, the DBX implemented in Solaris is much more than GDB, and you can see more information. It is worth noting that there is a system limit under Linux, which is the size of the core file. If this limit is set to 0, the program does not return to generate a Core file after an exception. If you want to get a Core file, use the ulimit -c command to adjust this parameter. Ulimit -a commands can check the current limit parameters of the system. 3. Common or order introduction The common command below Unix, which is very different from the console command under Windows. The command under UNIX may be an executing program, or a script that can be executed, and the system's commands can generally be found in / usr / bin / below. It is also necessary to explain, and UNIX strictly distinguishes the case case case, including the case of commands. Let's take a brief introduction to several commands commonly used under the UNIX system. 3.1 Common command list Ls lists files in the current directory, equivalent to Windows DIR. The CD switch directory is the same as the CD command under Windows. MKDIR creates a directory. RM deletes a file or directory. -r parameter indicates that the directory is deleted, and the -f parameter represents forced deletion. MV moves or modifies the file / directory name. CP copy file or directory, the -r parameter represents the object of the copy is a directory. PS View the process of the current system, -e is the most common parameter, indicating that all processes are listed. Man View Manual, this is the most common command, through him to view the user manual for the specified command or function. For example, Man PS can produce the help manual of the PS command, and Man Fopen can view the usage of the FOPEN function. Find looks up the specified file in the specified directory. GREP looks for the specified content in the specified file. VI edit text files, will be described in detail later. TAR file packages and unpacking tools, packaged through the CVF parameter, to unpack the GZIP compression tool via the XVF, can compress files into GZ files, unzipped through the -d parameter, often used together with the tar command. 3.2 Combination of Command In UNIX, you can use multiple commands to combine multiple commands, and the execution result of one command can be input as another command. Among them, the command used by other commands is GREP. in 2.3.1 In the kill.sh script, we use such a combination command "PS-E | GREP DEMO | AWK {'Print $ 1'}" to list the process number of all the names Demo in the current system . This usage is the most common method in our development process. In addition, if we want to know the network of our programs, you can use the netstat command and the grep command to use the status of the specified port, such as NetStat -a | GREP 43001, this command will list all in the current system 43001 The connection situation is connected. The usual grep command can only look up files in the current directory, such as: grep 'open_max' * .h is to find "Open_MAX" in all header files below the current directory. The Find command can find all subdirectories under the specified path, discover all matched files, then we can use the grep command and the Find command to implement the file content search in the subdirectory. The command format is as follows: GREP 'OPEN_MAX' `FIND / USR / INCLUDE -NAME '* .h'` This can find all headers in / usr / include and their subdirectories to see if" Open_MAX "is included. When executed, first execute the find command, form a list of files, and then use this file list as a parameter of GREP to perform the grep command. This is another way of command combination. 3.3 VI VI is the most commonly used text editor under UNIX, smart and powerful, once we take it together to do it. If you want to know more detailed information, perform Man VI to view it online help documentation. 3.3.1 Command mode and editing mode The working mode of the VI includes two types of command mode and editing mode. In command mode, some of the commands defined in the VI can be performed, which correspond to some specific keys, and all keyboards in command mode will be interpreted as commands. The edit mode is the mode of editing the document, and the corresponding content of all keyboards in editing mode is the content input as documentation. You can switch from the edit mode to the command mode from the editing mode via the ESC key. You can enter the edit mode from the command mode by some editing naming. 3.3.2 Basic order The basic command refers to the command execution in command mode, here we introduce several common commands: i Insert the editing mode I, enter the editing mode A, after the current characters are started Addition, enter the editing mode A, add, enter the editing mode X Remove the character x of the current cursor X De De De De De De De De De De De De De De De De De De De De De De De De De De De De De De De De De De De De De De De De De De De De De De De De De De De De De De De De De Deleting The operation G just jumped to the end of the file, in command mode, by entering '/' can be queried, and some other commands can be entered by input ':'. Enter ':' You can entered commands include: q Exit W Save WQ Save Exit Q! Forced exit, do not save W! Forced to write protected files, including read-only file set number display line numbers jump to a row 3.3.3 lookup and match The VI lookup feature is also very powerful, and in command mode, you can enter the lookup mode, you can enter the keyword you want to find. Then you can find the next place via 'n'. After entering ':', you can also enter some matching commands - "% s". The format of the command is ":% S / STR1 / STR 2 " After execution, all STR1 in the current file will be replaced into STR2. For a typical example, we said before, the text file under Windows passed into UNIX in binary, then the VI opened when the VI opened, there will be a "^ m", we can use VI to open This file is then removed by VI matching replacement function. "^ M". The command format is as follows::% s / ^ m // where "^ m" is entered by Ctrl V and Ctrl M.