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. 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.
Ø Document storage and reading
Similar to network transfer, if you write an integer to the file under Windows, then on the UNIX to open this file to read the data, you will 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 agreement of byte, restore data according to the byte order of its own platform
3. 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.
In the development of C , we often have such uses:
For (int i = 0; i { ... } This is the most commonly used for loop, because i is mainly used to control the loop, so it is generally not necessary to take it separately, just in the For statement. Here, simple variables such as I, J become our common variables, usually not named by the programming specification. It is this declarative method that has different understandings under Windows and Solaris, and the scope of I is different. Let's divide the role, as follows: { ... For (int i = 0; i Ii { I ... } ... ... } 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 { ... } ... For (i = 0; i { ... } B: For (int i = 0; i { ... } ... 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 tip, such a code is no problem: C: INT i = 0; IF (COND) { ... For (int i = 0; i { ... } ... } This is a correct code, although I have defined I, but redefine one I in For I nap, this is the syntax of C , which is not allowed in Java). But it is because this flexible mechanism of this C language has triggered a problem. The problem is generated from the code like A_B in the program, and then the declaration of I got the outside. In the process of later maintenance, a loop is added later, but it is increasing in the way C, which has a problem. Please see the following code: INT i = 0; CHAR STR1 [10]; CHAR STR2 [10]; STRCPY (STR1, "Hello"); ... For (i = 0; i <20; i ) { ... I } ... IF (COND) { For (int i = 0; i <10; i ) Iii { Ii IF (str1 [i] == 0) Break; } 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 of any function, such as: CMYOBJECT G_OBJECT; Normally, when the program starts, the system automatically calls the constructor of this object to initialize this global object, but in some systems (SCO UNIX), I don't want to expect, maybe this is compiled. A bug implemented by the device, 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; Thus, when the system is started, the New CMYObject is executed to allocate space for the object, and the constructor of the call object is executed to initialize the object. If you don't want to use a pointer to reference the object (for security factors, you don't want a function to set this northern needle during the program run), then we can use another method, as follows: CMYOBJECT & G_Object = * (New CMYObject); This can also 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. Have such a code: IF (NULL == PVAR) { ... } This is a good habit of most platforms, which can avoid the "==" to write "=" errors, can be found during compilation. 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 operating system characteristics There are some systems limitations in different operating systems. If the limit of the number of file handles, the Socket Wait restriction, the process, and thread stack size limit, so in the development process, these limit factors must be considered. Impact. 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. . Solve this problem, you can use a few ways: 1. Upgrade to 64-bit system or adopt 64-bit compiler 2. Use the function to operate in sys / io.h 3. 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 very different, 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. process Fork creation process POSIX thread library PTHREAD_CREATE Create a letter thread PTHREAD_ATTR_INIT initializes a thread properties object pthread_attr_destroy releases a thread properties object PTHREAD_EXIT terminates the thread that is called PTHREAD_JOIN hangs the current call thread until the end of the target thread PTHRead_setschedParam Sets the scheduling policy and priority of threads PThread_getschedparam gets thread scheduling policies and priorities PTHREAD_SIGMASK Change / Check the signal mask for calling threads PTHREAD_KILL sends a signal to another thread PTHREAD_SELF Returns the ID of the current thread PTHEAD_MUTEX_INIT initializes a mutex PTHREAD_MUTEXATTR_INIT initializes the property object of mutex PTHREAD_MUTEX_LOCK is set to a mutex, if the mutual exclusion has been locked by other threads, call the thread hang until the other thread release PTHREAD_MUTEX_UNLOCK Releases Mutual Exclusion (Unlock) Ptherad_mutex_destroy destroys a mutual exclusion PTHREAD_COND_INIT initialize a conditional variable PThread_Condattr_init initializes the properties object of a conditional variable PTHREAD_COND_WAIT blocks on a conditional variable PTHREAD_COND_SIGNAL releases the blocking of the next thread in condition variables PTHREAD_COND_BORADCAST releases all threads on this condition variable PTHREAD_COND_DESTROY destroy a conditional variable PTHREAD_CANCEL request to end a thread Solaris Local Gallery THR_CREATE Creates a new thread THR_EXIT termination call thread THR_JOIN hangs the current call thread until the end of the target thread THR_YIELD creates another thread with the current thread THR_SUSPEND hangs a specified thread THR_CONTINUE recovers a hang-haunted thread THR_SETPRIO Modify Thread Priority THR_GETPRIO gets the priority of threads THR_SIGSETMASK Change / Check the signal mask for calling threads THR_KILL sends a signal to another thread THR_SELF returns the ID of the current thread THR_MAIN tagged as the main thread THR_MUTEX_INIT initializes a mutex THR_MUTEX_LOCK to lock a mutex, if the mutex has been locked by other threads, call the thread hang until the other thread release THR_MUTEX_UNLOCK Releases Mutual Exclusion (Unlock) THR_MUTEX_DESTROY destroyed a mutual exclusion THR_COND_INIT initializes a conditional variable THR_COND_WAIT blocks on a conditional variable THR_COND_SIGNAL releases the blocking of the next thread in condition variables THR_COND_BORADCAST releases all threads on this condition variable THR_COND_DESTROY destroys any condition variables RWLOCK_INIT initializes a read and write lock RW_RDLOCK gets a read-write lock read lock RW_WRLOCK gets a write lock of a read and write lock RW_UNLOCK unlocks a read and write lock POSIX semaphore SEM_INIT initializes a semaphore SEM_DESTROY destroys a semaphore SEM_WAIT waits for a semaphore, the value of the semaphore is reduced by 1, if the current signal value bit is 0, the current thread is blocked, supporting some thread release signals SEM_TRYWAIT attempts to get a semaphore, the value of the semaphore is reduced by 1, if the current signal value is 0, return failed SEM_POST releases a semaphore SEM_GETVALUE gets the value of the specified semaphore SYSTEM V semaphore SemctL conducts a series of controls on the quantity Semget created a semaphore, returned to the ID of the signal when successfully Semop operates signals Solaris's local semaphore, closer to the signal light we have learned in the operating system SEMA_INIT initializes a signal light (selection) SEMA_DESTROY destroys a signal light SEMA_P executes the P operation of the signal light SEMA_P_SIG is similar to SEMA_P. When it is blocked, if the thread receives a signal, the function exits SEMA_TRYP Try to execute the P operation of the signal light SEMA_V executes the V operation of the signal light For convenience, I have already encapsulated the above commonly used functions in the development process, compatible with Windows and a variety of common UNIX systems, and there are many code resources available on the Internet. 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, there is only one Hello.cpp file engineering, you can compile: cc -o hello hello.cpp Where CC is a compiler, different systems may have different compilers below. 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: In the project, hello.cpp, func.cpp, other.cpp, we can use the following scripts to implement engineering compilation. CC -C Hello.cpp CC-C func.cpp Cc -c other.cpp Cc -o hello hello.o func.o other.o In the case of multiple files, separate the compilation and connection, first compile the source file one by one, then 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 # Target program name BIN_NAME = Demo # Compiler and compile parameters CC = GCC CXX = G CXXFLAGS = -g document list # Source code list SRCS = / Demo.cpp / Func.cpp # 目 目 文件 list, generate through the source code list Objs = $ {srcs: .cpp = .o} # 依赖 关 #depends All: $ {bin_name} .depends: $ {srcs} # reliance @echo create, depyle, please wait ... Dependency $ {Cxx} -m $ {srcs}> .depends # Execute command -include .depends #%. o:%. CPP # @Echo compling file: $? Please wait ... # $ {Cxx} $ {cxflags} -c $? $ {Bin_name}: $ {objs} @ e l linking file: $ @ please wait ... $ {Cxx} -o $ @ $ {objs} Clean: RM -F $ {bin_name} $ {objs} * pure .depends In the Makefile file, it is generally divided into three parts of "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 Operation and debugging Without Windows, UNIX can be executed only if there is executable permissions, 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. A typical directory structure is listed below: Mainpath program home directory Mainpath / bin executive directory Mainpath / lib shared library catalog In this case, you need to set the running environment of the program and 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. SetENV.SH: #! / bin / sh Path = `pwd` LD_LIBRARY_PATH = $ PATH / LIB: $ LD_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 It is worth noting that 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 debugging tool for debugging The debugging of the program is the most important part of the program development, and the bug in the program is found. 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) Operating procedures in debugging In the directory where the program is located, execute the GDB, you can enter the GDB debug interface with the program name as a parameter. Such as: GDB Demo 2) View the source file, set breakpoints Under 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 a breakpoint (if it is not the file where the main function is located), such as: Break Func.cpp: 10 Indicates that a breakpoint is set 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) Run the program After setting the break, you can run the program through the Run command under GDB. If the program needs to do, you can put it directly after the Run command, such as: Run -start Where -start is a program that allows the required parameters. 4) Data analysis When the program executes to breakpoint, wait for the user to process, which can view the current running status by some commands, including: Print prints the value of the variable, you only need to use the variable name to make a command parameter Where display program current call stack Set variable changes the value of the variable, it may affect the result of running after the program 5) Single step debugging After the breakpoint is completed, you can continue the program, and 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, unpacking through XVF Gzip compression tool, you can compress files into GZ files, unzipped through the -d parameter, often used with the tar command. 3.2 Combination of commands Below Unix, multiple commands can be used in combination, and the execution result of one command can be used as the input of 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 look for 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 that is executed by the knock button in command mode, here we introduce several common commands: i Insert and enter editing mode in the current start I Inserting in the lead, enter the editing mode a appended after the current character, enter the editing mode A append, enter the editing mode x Delete characters at the current cursor X Delete characters in front of the current cursor D Delete all characters from the cursor position to the end DD delete the current line DW Delete the current word u Cancel the operation G Jump to the end of the file In addition, in command mode, you can enter some other commands by input ':' can enter some commands. Enter ':' You can enter commands include: Q exit w Save WQ save exit Q! Forced exit, do not save W! Forced written to protected documents, including read-only files Set Number Display Line No Digital jumps to a line 3.3.3 Finding and Matching 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 //