Unix C语言编程示例

Unix C语言编程示例

时间:  2015-02-28 21:37
作者:  lsgxeva
分类:  基础深入 >>language>>C
摘要:  在unix的系统上编写一个简单的C语言测试演示
标签:  Freebsd Linux Unix C语言 测试演示
提示:  文章均来自网络,版权为原作者所有,如有侵犯权益,请联络我们.


1. gcc/g++ 命令的常用选项格式(选项  解释)
-o FILE           指定输出文件名,在编译为目标代码时,这一选项不是必须的。如果FILE没有指定,缺省文件名是a.out.
-c           只编译生成目标文件,不链接
-m486        针对 486 进行代码优化。
-O0          不进行优化处理。
-O 或 -O1  优化生成代码。
-O2          进一步优化。
-O3 比 -O2 更进一步优化,包括 inline 函数。
-w           关闭所有警告,建议不要使用此项
-Wall        允许发出gcc能提供的所有有用的警告,也可以用-W(warning)来标记指定的警告
-werror      把所有警告转换为错误,以在警告发生时中止编译过程                          
-MM          输出一个make兼容的相关列表
-v           显示在编译过程的每一步中用到的命令
-E           只运行 C 预编译器。
-shared      生成共享目标文件。通常用在建立共享库时。
-static      链接静态库,即执行静态链接
-lFOO        链接名为libFOO的函数库
-g           在可执行程序中包含标准调试信息
-ggdb        在可执行程序中包含只有GNU debugger才能使别的达两条是信息
-O           优化编译过的代码
-ON          指定代码优化的级别为N,o<=N<=3
-ansi        支持ANSI/ISO C的标准语法,取消GNU的语法扩展中与该标准有冲突的部分(但这一选项并不能保证生成ANSI兼容的代码) 这一选项将禁止 GNU C 的某些特色, 例如 asm 或 typeof 关键词。
-pedantic  允许发出ANSI/ISO C标准所列出的所有警告
-errors      允许发出ANSI/ISO C标准所列出的所有错误
-traditional           支持Kernighan & Ritchie C语法(如用旧式语法定义函数);如果不知道这个选项的含义,也没有关系
-IDIRECTORY      指定额外的头文件搜索路径DIRECTORY。
-LDIRECTORY      指定额外的函数库搜索路径DIRECTORY。
-DFOO=BAR 在命令行定义预处理宏FOO,其值为BAR
-IDIRNAME 将DIRNAME加入到头文件的搜索目录列表中
-LDIRNAME 将DIRNAME加入到库文件的搜索目录列表中,缺省情况下gcc 只链接共享库
-DMACRO      以字符串“1”定义 MACRO 宏。
-DMACRO=DEFN     以字符串“DEFN”定义 MACRO 宏。
-UMACRO      取消对 MACRO 宏的定义。


g++参数介绍

[介绍] 
gcc and g++分别是gnu的c & c++编译器   

gcc/g++在执行编译工作的时候,总共需要4步   
1.预处理,生成.i的文件  

    预处理器cpp
2.将预处理后的文件不转换成汇编语言,生成文件.s  

    编译器egcs
3.有汇编变为目标代码(机器代码)生成.o的文件

    汇编器as
4.连接目标代码,生成可执行程序

    连接器ld

1.总体选项

    -E   
只激活预处理,这个不生成文件,你需要把它重定向到一个输出文件里   
面.   
例子用法:   
gcc -E hello.c > pianoapan.txt   
gcc -E hello.c | more   
慢慢看吧,一个hello word 也要与处理成800行的代码      
    -S   
只激活预处理和编译,就是指把文件编译成为汇编代码。   
例子用法   
gcc -S hello.c   
他将生成.s的汇编代码,你可以用文本编辑器察看     
    -c    
只激活预处理,编译,和汇编,也就是他只把程序做成obj文件   
例子用法:   
gcc -c hello.c   
他将生成.o的obj文件  

2.目录选项

    -Idir   
在你是用#include"file"的时候,gcc/g++会先在当前目录查找你所制定的头   
文件,如果没有找到,他回到缺省的头文件目录找,如果使用-I制定了目录,他   
回先在你所制定的目录查找,然后再按常规的顺序去找.   
对于#include,gcc/g++会到-I制定的目录查找,查找不到,然后将到系   
统的缺省的头文件目录查找    

    -include file

    -i

相当于“#include”
包含某个代码,简单来说,就是便以某个文件,需要另一个文件的时候,就可以   
用它设定,功能就相当于在代码中使用#include   
例子用法:   
gcc hello.c -include /root/pianopan.h   
    -I-   
就是取消前一个参数的功能,所以一般在-Idir之后使用   
   -idirafter dir   
在-I的目录里面查找失败,讲到这个目录里面查找.   
    -iprefix prefix   
    -iwithprefix dir   
一般一起使用,当-I的目录查找失败,会到prefix+dir下查找    
    -Ldir   
制定编译的时候,搜索库的路径。比如你自己的库,可以用它制定目录,不然   
编译器将只在标准库的目录找。这个dir就是目录的名称。  
    -llibrary    
制定编译的时候使用的库   
例子用法   
gcc -lcurses hello.c   
使用ncurses库编译程序   

3.调试选项

     -g   
只是编译器,在编译的时候,产生调试信息。   
    -gstabs   
此选项以stabs格式声称调试信息,但是不包括gdb调试信息.   
    -gstabs+   
此选项以stabs格式声称调试信息,并且包含仅供gdb使用的额外调试信息.   
    -ggdb    
此选项将尽可能的生成gdb的可以使用的调试信息.

    -glevel

请求生成调试信息,同时用level指出需要多少信息,默认的level值是2

4.链接方式选项:

    -static 此选项将禁止使用动态库。

优点:程序运行不依赖于其他库

缺点:文件比较大

    -shared (-G) 此选项将尽量使用动态库,为默认选项

优点:生成文件比较小

缺点:运行时需要系统提供动态库

    -symbolic 建立共享目标文件的时候,把引用绑定到全局符号上.

对所有无法解析的引用作出警告(除非用连接编辑选项 `-Xlinker -z -Xlinker defs'取代)。

注:只有部分系统支持该选项.

5.错误与告警选项

    -Wall 一般使用该选项,允许发出GCC能够提供的所有有用的警告。也可以用-W{warning}来标记指定的警告。

    -pedantic 允许发出ANSI/ISO C标准所列出的所有警告

    -pedantic-errors 允许发出ANSI/ISO C标准所列出的错误

    -werror 把所有警告转换为错误,以在警告发生时中止编译过程

    -w 关闭所有警告,建议不要使用此项

6.预处理选项

    -Dmacro   
相当于C语言中的#define macro   
    -Dmacro=defn   
相当于C语言中的#define macro=defn   
    -Umacro   
相当于C语言中的#undef macro   
    -undef   
取消对任何非标准宏的定义 

7.其他选项

    -o

制定目标名称,缺省的时候,gcc 编译出来的文件是a.out,很难听,如果你和我有同感,改掉它,哈哈

例子用法   
gcc -o hello.exe hello.c (哦,windows用习惯了)   
gcc -o hello.asm -S hello.c   
    -O0   
    -O1   
    -O2   
    -O3   
编译器的优化选项的4个级别,-O0表示没有优化,-O1为缺省值,-O3优化级别最高

    -fpic 编译器就生成位置无关目标码.适用于共享库(shared library).

    -fPIC 编译器就输出位置无关目标码.适用于动态连接(dynamic linking),即使分支需要大范围转移.

    -v 显示详细的编译、汇编、连接命令
    -pipe   
使用管道代替编译中临时文件,在使用非gnu汇编工具的时候,可能有些问题   
gcc -pipe -o hello.exe hello.c   
    -ansi   
关闭gnu c中与ansi c不兼容的特性,激活ansi c的专有特性(包括禁止一些asm inline typeof关键字,以及UNIX,vax等预处理宏,   
    -fno-asm   
此选项实现ansi选项的功能的一部分,它禁止将asm,inline和typeof用作关键字。   
    -fno-strict-prototype   
只对g++起作用,使用这个选项,g++将对不带参数的函数,都认为是没有显式的对参数的个数和类型说明,而不是没有参数.而gcc无论是否使用这个参数,都将对没有带参数的函数,认为城没有显式说明的类型   
    -fthis-is-varialble   
就是向传统c++看齐,可以使用this当一般变量使用.   
    -fcond-mismatch   
允许条件表达式的第二和第三参数类型不匹配,表达式的值将为void类型   
    -funsigned-char   
    -fno-signed-char   
    -fsigned-char   
    -fno-unsigned-char   
这四个参数是对char类型进行设置,决定将char类型设置成unsigned char(前   
两个参数)或者 signed char(后两个参数) 
    -imacros file   
将file文件的宏,扩展到gcc/g++的输入文件,宏定义本身并不出现在输入文件中       
    -nostdinc   
使编译器不再系统缺省的头文件目录里面找头文件,一般和-I联合使用,明确限定头文件的位置   
    -nostdin C++   
规定不在g++指定的标准路经中搜索,但仍在其他路径中搜索,.此选项在创建libg++库使用   
    -C   
在预处理的时候,不删除注释信息,一般和-E使用,有时候分析程序,用这个很方便的   
    -M   
生成文件关联的信息。包含目标文件所依赖的所有源代码你可以用gcc -M hello.c来测试一下,很简单。   
    -MM   
和上面的那个一样,但是它将忽略由#include造成的依赖关系。   
    -MD   
和-M相同,但是输出将导入到.d的文件里面   
    -MMD   
和-MM相同,但是输出将导入到.d的文件里面   
    -Wa,option   
此选项传递option给汇编程序;如果option中间有逗号,就将option分成多个选项,然后传递给会汇编程序   
    -Wl.option   
此选项传递option给连接程序;如果option中间有逗号,就将option分成多个选项,然后传递给会连接程序.

    -x language filename   

设定文件所使用的语言,使后缀名无效,对以后的多个有效.也就是根   
据约定C语言的后缀名称是.c的,而C++的后缀名是.C或者.cpp,如果   
你很个性,决定你的C代码文件的后缀名是.pig 哈哈,那你就要用这   
个参数,这个参数对他后面的文件名都起作用,除非到了下一个参数   
的使用。   
可以使用的参数吗有下面的这些   
`c’, `objective-c’, `c-header’, `c++’, `cpp-output’,    
`assembler’, and `assembler-with-cpp’.   
看到英文,应该可以理解的。   
例子用法:   
gcc -x c hello.pig   
    -x none filename   
关掉上一个选项,也就是让gcc根据文件名后缀,自动识别文件类型   
例子用法:   
gcc -x c hello.pig -x none hello2.c




debug_pos.h
*******************************************************************************************
/***************************************************************************
Copyright (C), 2008-2015, LSGX.
        lsgxeva team. All rights reserved.

FileName:       debug_pos.h
ModuleName:     debug_pos
Version:        1.0
Date:           2014-11-14 22:55:26
CPU:            x86
RTOS:           Linux, FreeBSD
Compiler:       gcc
Author:         Jiang Jun-xing
Company:        LSGX
Description:    Debugging error message positioning
Others:         none

Include List:
1. ---- none
Macro List:
1. ---- DEBUG_POS(debug_level, ...)     // 按级别打印调试信息
2. ---- DEBUG_ASSERT(condition, ...)    // 断言打印调试信息
Structure List:
1. ---- enum ENUM_DEBUG_LEVEL           // 调试打印信息的级别
2. ---- struct DEBUG_STR                // 调试级别和调试标识
Function List:
1. ---- int system_digital_time(char * time_str, size_t str_len)         // 获取当前时间
2. ---- int get_process_name(char *process_name, size_t name_len)        // 获取当前进程pid的名称

History:
1. ---- Date:   2014-11-14 22:55:26
Version:        1.0
Author:         Jiang Jun-xing
Item:           lsgxeva
Modification:   none
***************************************************************************/

#ifndef __DEBUG_POS_H__
#define __DEBUG_POS_H__


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <ctype.h>
#include <sys/types.h>
#include <limits.h>
#include <time.h>
#include <stdarg.h>
#include <errno.h>
#include <signal.h>
#include <sys/wait.h>
#include <sys/utsname.h>


#ifdef __unix__

#include <stdbool.h>
#define DllExport extern

#else

#include <windows.h>
#define DllExport  __declspec( dllexport )

#endif // __unix__


#ifdef __cplusplus
extern "C" {
#endif // __cplusplus


// 整数累加并防止溢出
#define DBGP_INC_SAT( val )            ( val = ( (val) + 1 > (val) ) ? (val) + 1 : (val) )

// 返回数组元素的个数
#define DBGP_ARR_SIZE( arr )           ( sizeof((arr)) / sizeof((arr[0])) )

// 判断指针是否为空并返回字符串
#define DBGP_IS_NULL( ptr )            (!(ptr) ? "null" : "non-null")


/***************************************************************************
Structure: enum ENUM_DEBUG_LEVEL
Description: 调试打印信息的级别
Member:
1. ---  DEBUG_EMERG = 0         // DEBUG_EMERG 事件对应的调试信息等级
2. ---  DEBUG_ALERT = 1         // DEBUG_ALERT 事件对应的调试信息等级
3. ---  DEBUG_CRIT = 2          // DEBUG_CRIT 事件对应的调试信息等级
4. ---  DEBUG_ERR = 3           // DEBUG_ERR 事件对应的调试信息等级
5. ---  DEBUG_WARNING = 4       // DEBUG_WARNING 事件对应的调试信息等级
6. ---  DEBUG_NOTICE = 5        // DEBUG_NOTICE 事件对应的调试信息等级
7. ---  DEBUG_INFO = 6          // DEBUG_INFO 事件对应的调试信息等级
8. ---  DEBUG_DEBUG = 7         // DEBUG_DEBUG 事件对应的调试信息等级
Others: none
***************************************************************************/
enum ENUM_DEBUG_LEVEL {
        DEBUG_EMERG = 0,
        DEBUG_ALERT,
        DEBUG_CRIT,
        DEBUG_ERR,
        DEBUG_WARNING,
        DEBUG_NOTICE,
        DEBUG_INFO,
        DEBUG_DEBUG
};

#define DBGP_MAX_TITLE_LEN           20                      // 调试标识字符串的最大长度
#define DBGP_MIN_TIME_LEN            20                      // 存储时间字符串的最小长度
#define DBGP_MIN_PATH_LEN            512                     // 存储进程名称符串的最小长度
#define DBGP_LOG_FILE_NAME           "debug_pos.log"         // 缺省的日志记录的文件
#define DBGP_LOG_FILE_MODE           "at+"                   // 缺省的日志文件打开模式
#define DBGP_SER_MODE_NAME           "DEBUG"                 // 调试的程序名称
#define DBGP_LIMIT_KILL_LEVEL        DEBUG_ERR               // 结束进程的最大调试等级的等级

/***************************************************************************
Structure: struct DEBUG_STR
Description: 调试级别和调试标识
Member:
1. --- level    // 调试级别
2. --- title    // 调试标识
Others: none
***************************************************************************/
struct DEBUG_STR {
        const enum ENUM_DEBUG_LEVEL level;
        const char title[DBGP_MAX_TITLE_LEN];
};

DllExport struct DEBUG_STR DEBUG_STR_ITEM[DEBUG_DEBUG+1];

// 返回调试等级对应的标识
#define  DBGP_LEVEL_TITLE( debug_level )       (( debug_level >= 0 && debug_level <= ( DBGP_ARR_SIZE(DEBUG_STR_ITEM) - 1 ) ) ? DEBUG_STR_ITEM[debug_level].title : "level title unknow")

/***************************************************************************
Function: system_digital_time
Description: 获取当前时间
Calls: localtime        // 把从1970-1-1零点零分到当前时间系统所偏移的秒数时间转换为本地时间
Called By: DEBUG_POS    // 按级别打印调试信息的宏
Table Accessed: none
Table Updated: none
Input: str_len          // 字符串空间的长度
Output: time_str        // 存储时间的字符串指针
Return:
1. ---- right or success: 0
2. ---- error or fail: -1
Others: none
***************************************************************************/
DllExport int system_digital_time(char * time_str, const size_t str_len);

/***************************************************************************
Function: get_process_name
Description: 获取当前进程pid的名称
Calls: getpid           // 获取当前进程的PID
Called By: DEBUG_POS    // 按级别打印调试信息的宏
Table Accessed: none
Table Updated: none
Input: name_len         // 字符串空间的长度
Output: process_name    // 存储进程名称的字符串指针
Return:
1. ---- right or success: 0
1. ---- error or fail: -1
Others: none
***************************************************************************/
DllExport int get_process_name(char *process_name, const size_t name_len);

DllExport unsigned long long int debug_count;       // 调试消息数量计数

/***************************************************************************
Macro: DEBUG_POS
Description: 按级别打印调试信息的宏
Calls:  system_digital_time     // 获取当前时间
        get_process_name        // 获取当前进程pid的名称
        abort                   // 结束当前进程
Called By: ...
Table Accessed: none
Table Updated: none
Input:  debug_level     // 调试等级,枚举值(0-7)
        ...             // 可变参数,格式化字符串
Output: none
Return: none
Others: none
***************************************************************************/
// #define _DEBUG_POS_HIDE_
#ifndef _DEBUG_POS_HIDE_

#define DEBUG_POS(debug_level, ...)     do { \
        if ( debug_level >= 0 ) { \
                bool debug_exit_stat = false; \
                FILE * debug_pos_fp = NULL; \
                debug_pos_fp = fopen(DBGP_LOG_FILE_NAME, DBGP_LOG_FILE_MODE); \
                char time_str[DBGP_MAX_TITLE_LEN] = {'\0'}; \
                system_digital_time(time_str, sizeof(time_str)); \
                char process_name[DBGP_MIN_PATH_LEN] = {'\0'}; \
                get_process_name(process_name, sizeof(process_name)); \
                fprintf(debug_pos_fp, "[%s] <*** [%s] ***>\n\t[title: %s, time: %s, count: %llu]\n\t[file_name: %s, function_name: %s, line_no: %d]\n\t>>>> ", \
                        DBGP_SER_MODE_NAME, process_name, \
                        DBGP_LEVEL_TITLE(debug_level), \
                        time_str, DBGP_INC_SAT(debug_count), \
                        __FILE__, __FUNCTION__, __LINE__); \
                fprintf(debug_pos_fp, __VA_ARGS__); \
                fputc('\n', debug_pos_fp); \
                if (debug_level <= DBGP_LIMIT_KILL_LEVEL) { \
                        fprintf(debug_pos_fp, "%s", "\t>>>> ****** [debug exit abort process] ******\n"); \
                        debug_exit_stat = true; \
                } \
                fclose(debug_pos_fp); \
                if (debug_exit_stat) { \
                        abort(); \
                } \
        } \
} while(0)

#else

#define DEBUG_POS(debug_level, ...)     NULL

#endif // _DEBUG_POS_HIDE_


/***************************************************************************
Macro: DEBUG_ASSERT
Description: 断言打印调试信息的宏
Calls: DEBUG_POS        // 按级别打印调试信息的宏
Called By: ...
Table Accessed: none
Table Updated: none
Input:  condition       // 断言条件的真假
        ...             // 可变参数,格式化字符串
Output: none
Return: none
Others: none
***************************************************************************/
#define DEBUG_ASSERT(condition, ...)    do { \
        if (condition) { \
                NULL; \
        } else { \
                DEBUG_POS(DBGP_LIMIT_KILL_LEVEL, __VA_ARGS__); \
        } \
} while(0)


#ifdef __cplusplus
} /* extern "C" */
#endif // __cplusplus

#endif // __DEBUG_POS_H__

/* End of debug_pos.h */


*******************************************************************************************

debug_pos.c
*******************************************************************************************
/***************************************************************************
Copyright (C), 2008-2015, LSGX.
        lsgxeva team. All rights reserved.

FileName:       debug_pos.c
ModuleName:     debug_pos
Version:        1.0
Date:           2014-11-14 22:55:26
CPU:            x86
RTOS:           Linux, FreeBSD
Compiler:       gcc
Author:         Jiang Jun-xing
Company:        LSGX
Description:    Debugging error message positioning
Others:         none

Include List:
1. ---- none
Macro List:
1. ---- DEBUG_POS(debug_level, ...)     // 按级别打印调试信息
2. ---- DEBUG_ASSERT(condition, ...)    // 断言打印调试信息
Structure List:
1. ---- enum ENUM_DEBUG_LEVEL           // 调试打印信息的级别
2. ---- struct DEBUG_STR         // 调试级别和调试标识
Function List:
1. ---- int system_digital_time(char * time_str, size_t str_len)         // 获取当前时间
2. ---- int get_process_name(char *process_name, size_t name_len)        // 获取当前进程pid的名称

History:
1. ---- Date:   2014-11-14 22:55:26
Version:        1.0
Author:         Jiang Jun-xing
Item:           lsgxeva
Modification:   none
***************************************************************************/

#include "debug_pos.h"


#ifdef __cplusplus
extern "C" {
#endif // __cplusplus


/***************************************************************************
Structure: struct DEBUG_STR
Description: 调试级别和调试标识
Member:
1. --- level    // 调试级别
2. --- title    // 调试标识
Others: none
***************************************************************************/
struct DEBUG_STR DEBUG_STR_ITEM[DEBUG_DEBUG+1] = {
        {DEBUG_EMERG, "DEBUG_EMERG"},           /* system is unusable */ /* 紧急事件消息,系崩溃之前提示,表示系统不可用 */
        {DEBUG_ALERT, "DEBUG_ALERT"},           /* action must be taken immediately */ /* 报告消息,表示必须立即采取措施 */
        {DEBUG_CRIT, "DEBUG_CRIT"},             /* critical conditions */ /* 临界条件,通常涉及严重的硬件或软件操作失败 */
        {DEBUG_ERR, "DEBUG_ERR"},               /* error conditions */ /* 错误条件,驱动程序用KERN_ERR来报告硬件的错误 */
        {DEBUG_WARNING, "DEBUG_WARNING"},       /* warning conditions */ /* 警告条件,对可能现问题的情况进行警告 */
        {DEBUG_NOTICE, "DEBUG_NOTICE"},         /* normal but significant condition */ /* 正常又重要的条件,用于提醒 */
        {DEBUG_INFO, "DEBUG_INFO"},             /* informational */ /* 提示信息,如驱动程序启动时,打印硬件信息 */
        {DEBUG_DEBUG, "DEBUG_DEBUG"}            /* debug-level messages */ /* 调试级别的消息 */
};

/***************************************************************************
Function: system_digital_time
Description: 获取当前时间
Calls: localtime        // 把从1970-1-1零点零分到当前时间系统所偏移的秒数时间转换为本地时间
Called By: DEBUG_POS    // 按级别打印调试信息的宏
Table Accessed: none
Table Updated: none
Input: str_len          // 字符串空间的长度
Output: time_str        // 存储时间的字符串指针
Return:
1. ---- right or success: 0
2. ---- error or fail: -1
Others: none
***************************************************************************/
int system_digital_time(char * time_str, const size_t str_len)
{
        int iret = -1;

        if ( NULL == time_str || 0 == str_len ) {
                perror("parameter error");
                iret = -1;
                goto OUT;
        }

        if (str_len < DBGP_MIN_TIME_LEN) {
                perror("time_str buffer size to low");
                iret = -1;
                goto OUT;
        }

        time_t now = time((time_t *)NULL);
        struct tm * time_now = localtime(&now);

        memset((void *)time_str, '\0', str_len);
        snprintf(time_str, str_len, "%4d-%02d-%02d %02d:%02d:%02d",
                 time_now->tm_year + 1900,
                 time_now->tm_mon + 1,
                 time_now->tm_mday,
                 time_now->tm_hour,
                 time_now->tm_min,
                 time_now->tm_sec);

        iret = 0;
        return iret;

OUT:
        return iret;
}

/***************************************************************************
Function: get_process_name
Description: 获取当前进程pid的名称
Calls: getpid           // 获取当前进程的PID
Called By: DEBUG_POS    // 按级别打印调试信息的宏
Table Accessed: none
Table Updated: none
Input: name_len         // 字符串空间的长度
Output: process_name    // 存储进程名称的字符串指针
Return:
1. ---- right or success: 0
1. ---- error or fail: -1
Others: none
***************************************************************************/
int get_process_name(char *process_name, const size_t name_len)
{
        int iret = -1;

        if ( NULL == process_name || 0 == name_len ) {
                perror("parameter error");
                iret = -1;
                goto OUT;
        }

        if (name_len < DBGP_MIN_PATH_LEN) {
                perror("process_name buffer size to low");
                iret = -1;
                goto OUT;
        }

#ifdef __FreeBSD__
        const char *exe_file = "/file";
#else
        const char *exe_file = "/exe";
#endif

        char proc_path[256] = {'\0'};
        char pid_str[64] = {'\0'};
        char path[DBGP_MIN_PATH_LEN] = {'\0'};
        const char *proc_dir = "/proc/";
        pid_t pid = getpid();

        sprintf(pid_str, "%d", pid);
        strcpy(proc_path, proc_dir);
        strcat(proc_path, pid_str);
        strcat(proc_path, exe_file);

        int ch = readlink(proc_path, path, DBGP_MIN_PATH_LEN);
        if (ch != -1) {
                path[ch] = '\0';
                memset((void *)process_name, '\0', name_len);
                strncpy(process_name, path, ch);
                iret = 0;
        } else {
                iret = -1;
        }
        return iret;

OUT:
        return iret;
}

unsigned long long int debug_count = 0;       // 调试消息数量计数


#ifdef __cplusplus
} /* extern "C" */
#endif // __cplusplus

/* End of debug_pos.c */


*******************************************************************************************


demo.c
***********************************************************************************************
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

// #define _DEBUG_POS_HIDE_
#include "debug_pos.h"


int main(int argc, char *argv[], char *envp[])
{
        DEBUG_POS(DEBUG_DEBUG, "调试级别的消息");
        DEBUG_POS(DEBUG_INFO, "提示信息,如驱动程序启动时,打印硬件信息");
        DEBUG_POS(DEBUG_NOTICE, "正常又重要的条件,用于提醒");
        DEBUG_POS(DEBUG_WARNING, "警告条件,对可能现问题的情况进行警告");
        // DEBUG_POS(DEBUG_ERR, "错误条件,驱动程序用KERN_ERR来报告硬件的错误");
        // DEBUG_POS(DEBUG_CRIT, "临界条件,通常涉及严重的硬件或软件操作失败");
        // DEBUG_POS(DEBUG_ALERT, "报告消息,表示必须立即采取措施");
        DEBUG_POS(DEBUG_EMERG, "紧急事件消息,系崩溃之前提示,表示系统不可用");

        DEBUG_ASSERT(true, "断言成功消息");
        // DEBUG_ASSERT(false, "断言失败消息");

        DEBUG_POS(DEBUG_NOTICE, "You have inputed total [%d] argments", argc);
        for (int i = 0; i < argc; i++) {
                DEBUG_POS(DEBUG_NOTICE, "arg(%d):[%s]", i, argv[i]);
        }
        DEBUG_POS(DEBUG_NOTICE, "*** [The follow is envp] ***");
        for (int i = 0; envp[i] != NULL; i++) {
                DEBUG_POS(DEBUG_NOTICE, "envp(%d):[%s]", i, envp[i]);
        }

        return 0;
}


*******************************************************************************************



Makefile
********************************************************************************************
#############################################################################
#
# Generic Makefile for C/C++ Program
#
# License: GPL (General Public License)
# Author:  whyglinux <whyglinux AT gmail DOT com>
# Date:    2006/03/04 (version 0.1)
#          2007/03/24 (version 0.2)
#          2007/04/09 (version 0.3)
#          2007/06/26 (version 0.4)
#          2008/04/05 (version 0.5)
#
# Description:
# ------------
# This is an easily customizable makefile template. The purpose is to
# provide an instant building environment for C/C++ programs.
#
# It searches all the C/C++ source files in the specified directories,
# makes dependencies, compiles and links to form an executable.
#
# Besides its default ability to build C/C++ programs which use only
# standard C/C++ libraries, you can customize the Makefile to build
# those using other libraries. Once done, without any changes you can
# then build programs using the same or less libraries, even if source
# files are renamed, added or removed. Therefore, it is particularly
# convenient to use it to build codes for experimental or study use.
#
# GNU make is expected to use the Makefile. Other versions of makes
# may or may not work.
#
# Usage:
# ------
# 1. Copy the Makefile to your program directory.
# 2. Customize in the "Customizable Section" only if necessary:
#    * to use non-standard C/C++ libraries, set pre-processor or compiler
#      options to <MY_CFLAGS> and linker ones to <MY_LIBS>
#      (See Makefile.gtk+-2.0 for an example)
#    * to search sources in more directories, set to <SRCDIRS>
#    * to specify your favorite program name, set to <PROGRAM>
# 3. Type make to start building your program.
#
# Make Target:
# ------------
# The Makefile provides the following targets to make:
#   $ make           compile and link
#   $ make NODEP=yes compile and link without generating dependencies
#   $ make objs      compile only (no linking)
#   $ make tags      create tags for Emacs editor
#   $ make ctags     create ctags for VI editor
#   $ make clean     clean objects and the executable file
#   $ make distclean clean objects, the executable and dependencies
#   $ make help      get the usage of the makefile
#
#===========================================================================

## Customizable Section: adapt those variables to suit your program.
##==========================================================================

# The directories in which source files reside.
# If not specified, only the current directory will be serached.
SRCDIRS   = .

# The executable file name.
# If not specified, current directory name or `a.out' will be used.
TARGET_EXEC = demo
# BSD make provides $MACHINE, but GNU make doesn't
MACHINE ?= $(shell uname -m 2>/dev/null)
PROGRAM = $(addsuffix _$(MACHINE), $(TARGET_EXEC))

# Additional system include directories options.
INC_DIR     :=
INC_DIR     += /usr/include /usr/local/include
INC_DIR     += $(HOME)/include ${SRCDIRS}/include

ALL_INC_DIR  = $(addprefix -I, $(INC_DIR))

# Additional system library directories
LIB_DIR     :=
LIB_DIR     += /lib /usr/lib /usr/local/lib
LIB_DIR     += $(HOME)/include ${SRCDIRS}/include

ALL_LIB_DIR  = $(addprefix -L, $(LIB_DIR))

# The pre-processor options used by the cpp (man cpp for more).
CPPFLAGS    :=
#CPPFLAGS    += -Werror -pedantic-errors
CPPFLAGS    += -Wall -Wextra -pedantic -Wfloat-equal -funsigned-char

# The pre-processor and compiler options.
# Users can override those variables from the command line.
CFLAGS      :=
CFLAGS      += -Wshadow -Wstrict-prototypes -Wpointer-arith -Wcast-qual -Wcast-align -Wwrite-strings -Wmissing-prototypes -Wnested-externs -Winline -Wundef
#CFLAGS      += -pipe -ffast-math -g -pg -ggdb -O2
CFLAGS      += -U__STRICT_ANSI__ -std=gnu99
#CFLAGS      += -D_DEBUG_POS_HIDE_

CXXFLAGS    :=
CXXFLAGS    += -fno-strict-prototype -Wctor-dtor-privacy -Wnon-virtual-dtor -Woverloaded-virtual -Wreorder

# The options used in linking as well as in any direct use of ld.
LDFLAGS     :=
LDFLAGS     += -Wl,-rpath=/usr/local/lib/gcc48
LDFLAGS     += -lm -lpthread -lncurses
LDFLAGS     += -lssl -lcrypto

## Implicit Section: change the following only when necessary.
##==========================================================================

# The source file types (headers excluded).
# .c indicates C source files, and others C++ ones.
SRCEXTS = .c .C .cc .cpp .CPP .c++ .cxx .cp

# The header file types.
HDREXTS = .h .H .hh .hpp .HPP .h++ .hxx .hp

# The C program compiler.
CC     = gcc

# The C++ program compiler.
CXX    = g++

# Un-comment the following line to compile C programs as C++ ones.
#CC     = $(CXX)

# The command used to delete file.
RM     = rm -f

ETAGS = etags
ETAGSFLAGS =

CTAGS = ctags
CTAGSFLAGS =

## Stable Section: usually no need to be changed. But you can add more.
##==========================================================================
SHELL   = /bin/bash
EMPTY   =
SPACE   = $(EMPTY) $(EMPTY)
ifeq ($(PROGRAM),)
  CUR_PATH_NAMES = $(subst /,$(SPACE),$(subst $(SPACE),_,$(CURDIR)))
  PROGRAM = $(word $(words $(CUR_PATH_NAMES)),$(CUR_PATH_NAMES))
  ifeq ($(PROGRAM),)
    PROGRAM = a.out
  endif
endif
ifeq ($(SRCDIRS),)
  SRCDIRS = .
endif
SOURCES = $(foreach d,$(SRCDIRS),$(wildcard $(addprefix $(d)/*,$(SRCEXTS))))
HEADERS = $(foreach d,$(SRCDIRS),$(wildcard $(addprefix $(d)/*,$(HDREXTS))))
SRC_CXX = $(filter-out %.c,$(SOURCES))
OBJS    = $(addsuffix .o, $(basename $(SOURCES)))
DEPS    = $(OBJS:.o=.d)

## Define some useful variables.
DEP_OPT = $(shell if `$(CC) --version | grep "GCC" >/dev/null`; then \
                  echo "-MM -MP"; else echo "-M"; fi )
DEPEND      = $(CC)  $(DEP_OPT) $(ALL_INC_DIR) $(CPPFLAGS) $(CFLAGS)
DEPEND.d    = $(subst -g ,,$(DEPEND))
COMPILE.c   = $(CC) $(ALL_INC_DIR) $(CPPFLAGS) $(CFLAGS) -c
COMPILE.cxx = $(CXX) $(ALL_INC_DIR) $(CPPFLAGS) $(CXXFLAGS) -c
LINK.c      = $(CC) $(ALL_INC_DIR) $(CPPFLAGS) $(CFLAGS) $(ALL_LIB_DIR) $(LDFLAGS)
LINK.cxx    = $(CXX) $(ALL_INC_DIR) $(CPPFLAGS) $(CXXFLAGS) $(ALL_LIB_DIR) $(LDFLAGS)

.PHONY: all objs tags ctags clean distclean help show

# Delete the default suffixes
.SUFFIXES:

all: $(PROGRAM)

# Rules for creating dependency files (.d).
#------------------------------------------

%.d:%.c
@echo -n $(dir $<) > $@
@$(DEPEND.d) $< >> $@

%.d:%.C
@echo -n $(dir $<) > $@
@$(DEPEND.d) $< >> $@

%.d:%.cc
@echo -n $(dir $<) > $@
@$(DEPEND.d) $< >> $@

%.d:%.cpp
@echo -n $(dir $<) > $@
@$(DEPEND.d) $< >> $@

%.d:%.CPP
@echo -n $(dir $<) > $@
@$(DEPEND.d) $< >> $@

%.d:%.c++
@echo -n $(dir $<) > $@
@$(DEPEND.d) $< >> $@

%.d:%.cp
@echo -n $(dir $<) > $@
@$(DEPEND.d) $< >> $@

%.d:%.cxx
@echo -n $(dir $<) > $@
@$(DEPEND.d) $< >> $@

# Rules for generating object files (.o).
#----------------------------------------
objs:$(OBJS)

%.o:%.c
$(COMPILE.c) $< -o $@

%.o:%.C
$(COMPILE.cxx) $< -o $@

%.o:%.cc
$(COMPILE.cxx) $< -o $@

%.o:%.cpp
$(COMPILE.cxx) $< -o $@

%.o:%.CPP
$(COMPILE.cxx) $< -o $@

%.o:%.c++
$(COMPILE.cxx) $< -o $@

%.o:%.cp
$(COMPILE.cxx) $< -o $@

%.o:%.cxx
$(COMPILE.cxx) $< -o $@

# Rules for generating the tags.
#-------------------------------------
tags: $(HEADERS) $(SOURCES)
$(ETAGS) $(ETAGSFLAGS) $(HEADERS) $(SOURCES)

ctags: $(HEADERS) $(SOURCES)
$(CTAGS) $(CTAGSFLAGS) $(HEADERS) $(SOURCES)

# Rules for generating the executable.
#-------------------------------------
$(PROGRAM):$(OBJS)
ifeq ($(SRC_CXX),)              # C program
$(LINK.c)   $(OBJS) $(MY_LIBS) -o $@
@echo Type ./$@ to execute the program.
else                            # C++ program
$(LINK.cxx) $(OBJS) $(MY_LIBS) -o $@
@echo Type ./$@ to execute the program.
endif

# MODIFY START
#ifndef NODEP
ifdef NODEP
# MODIFY END
ifneq ($(DEPS),)
  sinclude $(DEPS)
endif
endif

clean:
$(RM) $(OBJS) $(PROGRAM) $(PROGRAM).exe $(PROGRAM).elf $(PROGRAM).gmon

distclean: clean
$(RM) $(DEPS) TAGS

# Show help.
help:
@echo 'Generic Makefile for C/C++ Programs (gcmakefile) version 0.5'
@echo 'Copyright (C) 2007, 2008 whyglinux <[email protected]>'
@echo
@echo 'Usage: make [TARGET]'
@echo 'TARGETS:'
@echo '  all       (=make) compile and link.'
@echo '  NODEP=yes make without generating dependencies.'
@echo '  objs      compile only (no linking).'
@echo '  tags      create tags for Emacs editor.'
@echo '  ctags     create ctags for VI editor.'
@echo '  clean     clean objects and the executable file.'
@echo '  distclean clean objects, the executable and dependencies.'
@echo '  show      show variables (for debug use only).'
@echo '  help      print this message.'
@echo
@echo 'Report bugs to <whyglinux AT gmail DOT com>.'

# Show variables (for debug use only.)
show:
@echo 'PROGRAM     :' $(PROGRAM)
@echo 'SRCDIRS     :' $(SRCDIRS)
@echo 'HEADERS     :' $(HEADERS)
@echo 'SOURCES     :' $(SOURCES)
@echo 'SRC_CXX     :' $(SRC_CXX)
@echo 'OBJS        :' $(OBJS)
@echo 'DEPS        :' $(DEPS)
@echo 'DEPEND      :' $(DEPEND)
@echo 'COMPILE.c   :' $(COMPILE.c)
@echo 'COMPILE.cxx :' $(COMPILE.cxx)
@echo 'link.c      :' $(LINK.c)
@echo 'link.cxx    :' $(LINK.cxx)

## End of the Makefile ##  Suggestions are welcome  ## All rights reserved ##
#############################################################################


********************************************************************************************





来自为知笔记(Wiz)


附件列表

     

    你可能感兴趣的:(Unix C语言编程示例)