kinve 4 年 前
コミット
133f975a4a

+ 1 - 0
README.md

@@ -0,0 +1 @@
+linux 通用函数

+ 208 - 0
comm/commGPIO.c

@@ -0,0 +1,208 @@
+#include "commGPIO.h"
+
+int gpio_export(int pin)  
+{  
+    char buffer[64];  
+    int len;  
+    int fd;  
+  
+    fd = open("/sys/class/gpio/export", O_WRONLY);  
+    if (fd < 0) {  
+        MSG("Failed to open export for writing!");  
+        return(-1);  
+    }  
+  
+    len = snprintf(buffer, sizeof(buffer), "%d", pin);  
+    if (write(fd, buffer, len) < 0) {  
+        MSG("Failed to export gpio!");  
+        return -1;  
+    }  
+     
+    close(fd);  
+    return 0;  
+}  
+
+int gpio_unexport(int pin)  
+{  
+    char buffer[64];  
+    int len;  
+    int fd;  
+  
+    fd = open("/sys/class/gpio/unexport", O_WRONLY);  
+    if (fd < 0) {  
+        MSG("Failed to open unexport for writing!");  
+        return -1;  
+    }  
+  
+    len = snprintf(buffer, sizeof(buffer), "%d", pin);  
+    if (write(fd, buffer, len) < 0) {  
+        MSG("Failed to unexport gpio!");  
+        return -1;  
+    }  
+     
+    close(fd);  
+    return 0;  
+} 
+
+//dir: 0-->IN, 1-->OUT
+int gpio_direction(int pin, int dir)  
+{  
+    static const char dir_str[] = "in\0out";  
+    char path[64];  
+    int fd;  
+  
+    snprintf(path, sizeof(path), "/sys/class/gpio/gpio%d/direction", pin);  
+    fd = open(path, O_WRONLY);  
+    if (fd < 0) {  
+        MSG("Failed to open gpio direction for writing!");  
+        return -1;  
+    }  
+  
+    if (write(fd, &dir_str[dir == 0 ? 0 : 3], dir == 0 ? 2 : 3) < 0) {  
+        MSG("Failed to set direction!");  
+        return -1;  
+    }  
+  
+    close(fd);  
+    return 0;  
+}  
+
+//value: 0-->LOW, 1-->HIGH
+int gpio_write(int pin, int value)  
+{  
+    static const char values_str[] = "01";  
+    char path[64];  
+    int fd;  
+  
+    snprintf(path, sizeof(path), "/sys/class/gpio/gpio%d/value", pin);  
+    fd = open(path, O_WRONLY);  
+    if (fd < 0) {  
+        MSG("Failed to open gpio value for writing!");  
+        return -1;  
+    }  
+  
+    if (write(fd, &values_str[value == 0 ? 0 : 1], 1) < 0) {  
+        MSG("Failed to write value!");  
+        return -1;  
+    }  
+  
+    close(fd);  
+    return 0;  
+}
+
+int gpio_read(int pin)  
+{  
+    char path[64];  
+    char value_str[3];  
+    int fd;  
+  
+    snprintf(path, sizeof(path), "/sys/class/gpio/gpio%d/value", pin);  
+    fd = open(path, O_RDONLY);  
+    if (fd < 0) {  
+        MSG("Failed to open gpio value for reading!");  
+        return -1;  
+    }  
+  
+    if (read(fd, value_str, 3) < 0) {  
+        MSG("Failed to read value!");  
+        return -1;  
+    }  
+  
+    close(fd);  
+    return (atoi(value_str));
+}  
+
+// none表示引脚为输入,不是中断引脚
+// rising表示引脚为中断输入,上升沿触发
+// falling表示引脚为中断输入,下降沿触发
+// both表示引脚为中断输入,边沿触发
+// 0-->none, 1-->rising, 2-->falling, 3-->both
+int gpio_edge(int pin, int edge)
+{
+	const char dir_str[] = "none\0rising\0falling\0both"; 
+	int ptr;
+	char path[64];  
+	int fd; 
+
+	switch(edge){
+	case 0:
+		ptr = 0;
+		break;
+	case 1:
+		ptr = 5;
+		break;
+	case 2:
+		ptr = 12;
+		break;
+	case 3:
+		ptr = 20;
+		break;
+	default:
+		ptr = 0;
+		break;
+	} 
+  
+    snprintf(path, sizeof(path), "/sys/class/gpio/gpio%d/edge", pin);  
+    fd = open(path, O_WRONLY);  
+    if (fd < 0) {  
+        MSG("Failed to open gpio edge for writing!");  
+        return -1;  
+    }  
+  
+    if (write(fd, &dir_str[ptr], strlen(&dir_str[ptr])) < 0) {  
+        MSG("Failed to set edge!");  
+        return -1;  
+    }  
+  
+    close(fd);  
+    return 0;  
+}
+
+//实现中断检测函数
+//GPIO1_17
+int main_test()  
+{  
+	int gpio_fd, ret;
+	struct pollfd fds[1];
+	char buff[10];
+	unsigned char cnt = 0;
+	//LED引脚初始化
+	gpio_export(115);
+	gpio_direction(115, 1);
+	gpio_write(115, 0);
+
+	//按键引脚初始化
+	gpio_export(49);
+	gpio_direction(49, 0);
+	gpio_edge(49,1);
+	gpio_fd = open("/sys/class/gpio/gpio49/value",O_RDONLY);
+	if(gpio_fd < 0){
+		MSG("Failed to open value!");  
+		return -1;  
+	}
+	fds[0].fd = gpio_fd;
+	fds[0].events  = POLLPRI;
+	ret = read(gpio_fd,buff,10);
+	if( ret == -1 )
+		MSG("read");
+
+	while(1){
+		ret = poll(fds,1,0);
+		if( ret == -1 )
+			MSG("poll\n");
+		if( fds[0].revents & POLLPRI){
+			ret = lseek(gpio_fd,0,SEEK_SET);
+			if( ret == -1 )
+				MSG("lseek");
+
+			ret = read(gpio_fd,buff,10);
+			if( ret == -1 )
+				MSG("read");
+
+			gpio_write(115, cnt++%2);
+		}
+		usleep(100000);
+	}
+	return 0;
+}  
+

+ 30 - 0
comm/commGPIO.h

@@ -0,0 +1,30 @@
+#ifndef _commGPIO_H_
+#define _commGPIO_H_ 
+ 
+#include <stdio.h>
+#include <string.h> 
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>  
+#include <stdarg.h> 
+#include <time.h>
+#include <assert.h>
+#include <errno.h>
+
+#include <stdlib.h>  
+#include <fcntl.h> 
+#include <poll.h>
+
+#include "commLOG.h"
+//#define MSG(args...) printf(args) 
+#define MSG(fmt, args...) DBGLog(fmt, ##args) 
+
+//函数声明
+int gpio_export(int pin);
+int gpio_unexport(int pin);
+int gpio_direction(int pin, int dir);	//dir: 0-->IN, 1-->OUT
+int gpio_write(int pin, int value);		//value: 0-->LOW, 1-->HIGH
+int gpio_read(int pin);
+int gpio_edge(int pin, int edge);		//edge: 0-->none, 1-->rising, 2-->falling, 3-->both
+
+#endif

+ 57 - 0
comm/commLOG.c

@@ -0,0 +1,57 @@
+#include "commLOG.h"
+
+//日志的编号
+int giInfoNumb = 1;
+int debugInfo(char *pLogPath, char *pFile, const char *pFuncName, int iLineNumb, char *fmt, ...)
+{
+    if(NULL == pLogPath ||'\0' == pLogPath[0] || NULL == pFile || '\0' == pFile[0] || NULL == pFuncName ||'\0' == pFuncName[0]){
+		printf("debugInfo param err:%s,%s,%s,%d\r\n", pLogPath, pFile, pFuncName, iLineNumb);
+        return LOG_VS_ERR;
+	}
+    //判断文件大小是否清空该文件,每1000次写日志里检测1次文件大小
+    if(0 == (giInfoNumb % 10))
+    {
+        struct stat fileStat;
+        if((giInfoNumb >= LOG_LINE_MAX) || ((0 == stat(pLogPath, &fileStat)) && (fileStat.st_size > LOG_SIZE_MAX))){
+			printf("\ndebugInfo log too big,%dline,%dbyte\n", giInfoNumb, (int)fileStat.st_size);
+            remove(pLogPath);
+			giInfoNumb = 0;
+		}
+    }
+
+    //写入日期、函数信息
+    time_t timeSecs = time(NULL);
+    struct tm *timeInfo = localtime(&timeSecs);
+    char acTitle[LOG_STR_LEN_1024] = { 0 };
+	char debugMsg[LOG_STR_LEN_512] = { 0 };
+	
+    va_list args;
+    va_start(args, fmt);
+    vsnprintf(debugMsg, sizeof(debugMsg), fmt, args);
+    va_end(args);
+#if 0    
+    snprintf(acTitle, sizeof(acTitle), "[%04d] [%d%02d%02d/%02d:%02d:%02d] [%s] [%s:%d] %s\n", giInfoNumb++,
+             timeInfo->tm_year + 1900, timeInfo->tm_mon + 1, timeInfo->tm_mday, 
+             timeInfo->tm_hour, timeInfo->tm_min, timeInfo->tm_sec, pFile, pFuncName, iLineNumb,
+			 acTitle);
+#else	
+	//节约空间
+    snprintf(acTitle, sizeof(acTitle), "%02d %02d/%02d:%02d:%02d %s\n", giInfoNumb++,
+            timeInfo->tm_mday,timeInfo->tm_hour, timeInfo->tm_min, timeInfo->tm_sec,
+			debugMsg); 
+#endif
+	//调试打印
+	printf(acTitle);
+
+    //打开文件,写入日志
+    FILE *pLogHandle = fopen(pLogPath, "a+");
+    if(NULL == pLogHandle){
+		printf("ERROR,debugInfo:fopen=%s\n",strerror(errno));
+        return LOG_VS_ERR;
+	}
+    int iLen = strlen(acTitle);
+    fwrite(acTitle, iLen, 1, pLogHandle);
+	fclose(pLogHandle);
+    
+    return LOG_VS_OK;
+}

+ 34 - 0
comm/commLOG.h

@@ -0,0 +1,34 @@
+#ifndef _commLOG_H_
+#define _commLOG_H_ 
+ 
+#include <stdio.h>
+#include <string.h> 
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>  
+#include <stdarg.h> 
+#include <time.h>
+#include <assert.h>
+#include <errno.h>
+
+#define LOG_SIZE_MAX           4096 	//16777216             //1024*1024*16=16M
+#define LOG_LINE_MAX           120  	//1000
+#define LOG_FILE_PATH          "/root/door-ctrl/log-door-ctrl"        //日志文件路径
+#define LOG_PARAMS             LOG_FILE_PATH,__FILE__,__func__,__LINE__ //日志文件路径 调用函数所在文件 调用函数名 调用debugInfo时所在行号
+
+//显示调用debugInfo接口的函数所在的文件名、函数名、行号
+//调用举例:  debuInfo(LOG_PARAMS, “some string %s, some int %d and so on", "hello log", 101);
+
+#if 1
+int debugInfo(char *pLogPath, char *pFile, const char *pFuncName, int iLineNumb, char *fmt, ...);
+#define DBGLog(fmt, args...) debugInfo(LOG_PARAMS, fmt, ##args) 
+#else
+#define DBGLog(fmt, args...) do{}while(0)
+#endif
+ 
+#define LOG_VS_ERR 0
+#define LOG_VS_OK  1
+#define LOG_STR_LEN_1024 1024
+#define LOG_STR_LEN_512  512
+
+#endif

+ 56 - 0
comm/commMsgQueue.c

@@ -0,0 +1,56 @@
+#include "commMsgQueue.h"
+static int commMsgQueue(int flags)
+{
+    key_t _key = ftok(PATHNAME,PROJ_ID);//ftok参数有两个,第一个是路径变量,第二个是projectID
+    if(_key < 0){
+        perror("ftok");
+        return -1;
+    }
+    int msgid = msgget(_key,flags);
+    if(msgid < 0){
+        perror("msgget");
+        return -2;
+    }
+    return msgid;
+}
+ 
+int creatMsgQueue()
+{
+    return commMsgQueue(IPC_CREAT | IPC_EXCL|0666);
+}
+ 
+int getMsgQueue()
+{   
+    return commMsgQueue(IPC_CREAT);
+}
+ 
+int destroyMsgQueue(int msgid)
+{
+    if(msgctl(msgid, IPC_RMID, NULL) < 0){
+        perror("msgctl");
+        return -1;
+    }
+    return 0;
+}
+int sendMsg(int msgid, int type, const char *msg)
+{
+    struct msgbuf _mb;
+    _mb.mtype = type;
+    strcpy(_mb.mtext,msg);
+    if(msgsnd(msgid, &_mb,sizeof(_mb.mtext),0)<0){
+        perror("msgsnd");
+        return -1;
+    }
+    return 0;
+}
+int recvMsg(int msgid, int type, char *out)
+{
+    struct msgbuf _mb;
+    if(msgrcv(msgid, &_mb, sizeof(_mb.mtext),type,IPC_NOWAIT)<0){	//0.阻塞 IPC_NOWAIT.非阻塞
+        //perror("msgrcv");
+        return -1;
+    }
+ 
+    strcpy(out,_mb.mtext);
+    return 0;
+}

+ 34 - 0
comm/commMsgQueue.h

@@ -0,0 +1,34 @@
+#ifndef _commMsgQueue_H_
+#define _commMsgQueue_H_ 
+ 
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/ipc.h>
+#include <sys/msg.h>
+#include <string.h>
+ 
+#define PATHNAME "."
+#define PROJ_ID 0x0824
+
+enum{
+	QUEUE_MSG_CLIENT,		//客户端
+	QUEUE_MSG_POST,			//网页端
+	QUEUE_MSG_UNLOCK,		//开锁
+	QUEUE_MSG_MAX			//最大
+};
+
+ 
+struct msgbuf{
+    long mtype;
+    char mtext[1024];
+};
+int creatMsgQueue();
+int getMsgQueue();
+int destroyMsgQueue(int msgid);
+int sendMsg(int msgid, int type, const char *msg);
+int recvMsg(int msgid, int type, char *out);
+ 
+ 
+ 
+ 
+#endif

+ 80 - 0
comm/commSingleApp.c

@@ -0,0 +1,80 @@
+/**************************************************************************************************
+**                                                                                               **
+**  文件名称:  commSingleApp.c                                                                 **
+**  版权所有:  CopyRight @ LEON WorkStudio CO.LTD. 2017                                          **
+**  文件描述:  判断系统中是否已经存在该进程的实例                                                **
+**  ===========================================================================================  **
+**  创建信息:  | 2017-9-14 | LEON | 创建本模块                                                   **
+**  ===========================================================================================  **
+**  修改信息:  单击此处添加....                                                                  **
+**************************************************************************************************/
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <printf.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include "commSingleApp.h"
+/**************************************************************************************************
+**  函数名称:  lockfile
+**  功能描述:  对文件加锁
+**  输入参数:  无
+**  输出参数:  无
+**  返回参数:  无
+**************************************************************************************************/
+static int lockfile(int fd)
+{
+    struct flock fl;
+
+    fl.l_type   = F_WRLCK;
+    fl.l_start  = 0;
+    fl.l_whence = SEEK_SET;
+    fl.l_len    = 0;
+
+    return(fcntl(fd, F_SETLK, &fl));
+}
+
+/**************************************************************************************************
+**  函数名称:  proc_is_exist
+**  功能描述:  判断系统中是否存在该进程
+**  输入参数:  procname: 进程名
+**  输出参数:  无
+**  返回参数:  返回1表示系统中已经存在该进程了;返回0表示系统中不存在该进程
+**  注意事项:  此处加锁完后无需对文件进行close,而是进程退出后由系统来释放;否则无法起到保护的作用
+**************************************************************************************************/
+int proc_is_exist(const char *procname)
+{
+    int  fd;
+    char buf[16];
+    char filename[100];
+
+    sprintf(filename, "/var/run/%s.pid", procname);
+
+    fd = open(filename, O_RDWR | O_CREAT, (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH));
+    if (fd < 0) {
+        printf("open file \"%s\" failed!!!\n", filename);
+        return 1;
+    }
+
+    if (lockfile(fd) == -1) {                                                  /* 尝试对文件进行加锁 */
+        printf("file \"%s\" locked. proc already exit!!!\n", filename);
+        close(fd);
+        return 1;
+    } else {
+        ftruncate(fd, 0);                                                      /* 写入运行实例的pid */
+        sprintf(buf, "%ld", (long)getpid());
+        write(fd, buf, strlen(buf) + 1);
+        return 0;
+    }
+}
+
+#if 0 //测试
+if (proc_is_exist(g_fk_process_name) == TRUE) {                             /* 单实例运行 */
+    print_sys("an \"%s\" already running in system. exit now...\n", g_fk_process_name);
+    return 0;
+} else {
+    print_sys("\"%s\" starting...\n", g_fk_process_name);
+}
+#endif

+ 25 - 0
comm/commSingleApp.h

@@ -0,0 +1,25 @@
+/**************************************************************************************************
+**                                                                                               **
+**  文件名称:  commSingleApp.h                                                                 **
+**  版权所有:  CopyRight @ LEON WorkStudio CO.LTD. 2017                                          **
+**  文件描述:  判断系统中是否已经存在该进程的实例                                                **
+**  ===========================================================================================  **
+**  创建信息:  | 2017-9-14 | LEON | 创建本模块                                                   **
+**  ===========================================================================================  **
+**  修改信息:  单击此处添加....                                                                  **
+**************************************************************************************************/
+#ifndef COMM_SINGLE_APP_H
+#define COMM_SINGLE_APP_H
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+int proc_is_exist(const char *procname);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif

+ 80 - 0
单实例进程/single_instance.c

@@ -0,0 +1,80 @@
+/**************************************************************************************************
+**                                                                                               **
+**  文件名称:  single_instance.c                                                                 **
+**  版权所有:  CopyRight @ LEON WorkStudio CO.LTD. 2017                                          **
+**  文件描述:  判断系统中是否已经存在该进程的实例                                                **
+**  ===========================================================================================  **
+**  创建信息:  | 2017-9-14 | LEON | 创建本模块                                                   **
+**  ===========================================================================================  **
+**  修改信息:  单击此处添加....                                                                  **
+**************************************************************************************************/
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <printf.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/stat.h>
+
+/**************************************************************************************************
+**  函数名称:  lockfile
+**  功能描述:  对文件加锁
+**  输入参数:  无
+**  输出参数:  无
+**  返回参数:  无
+**************************************************************************************************/
+static int lockfile(int fd)
+{
+    struct flock fl;
+
+    fl.l_type   = F_WRLCK;
+    fl.l_start  = 0;
+    fl.l_whence = SEEK_SET;
+    fl.l_len    = 0;
+
+    return(fcntl(fd, F_SETLK, &fl));
+}
+
+/**************************************************************************************************
+**  函数名称:  proc_is_exist
+**  功能描述:  判断系统中是否存在该进程
+**  输入参数:  procname: 进程名
+**  输出参数:  无
+**  返回参数:  返回1表示系统中已经存在该进程了;返回0表示系统中不存在该进程
+**  注意事项:  此处加锁完后无需对文件进行close,而是进程退出后由系统来释放;否则无法起到保护的作用
+**************************************************************************************************/
+int proc_is_exist(const char *procname)
+{
+    int  fd;
+    char buf[16];
+    char filename[100];
+
+    sprintf(filename, "/var/run/%s.pid", procname);
+
+    fd = open(filename, O_RDWR | O_CREAT, (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH));
+    if (fd < 0) {
+        printf("open file \"%s\" failed!!!\n", filename);
+        return 1;
+    }
+
+    if (lockfile(fd) == -1) {                                                  /* 尝试对文件进行加锁 */
+        printf("file \"%s\" locked. proc already exit!!!\n", filename);
+        close(fd);
+        return 1;
+    } else {
+        ftruncate(fd, 0);                                                      /* 写入运行实例的pid */
+        sprintf(buf, "%ld", (long)getpid());
+        write(fd, buf, strlen(buf) + 1);
+        return 0;
+    }
+}
+
+#if 0 //测试
+if (proc_is_exist(g_fk_process_name) == TRUE) {                             /* 单实例运行 */
+    print_sys("an \"%s\" already running in system. exit now...\n", g_fk_process_name);
+    return 0;
+} else {
+    print_sys("\"%s\" starting...\n", g_fk_process_name);
+}
+#endif

+ 25 - 0
单实例进程/single_instance.h

@@ -0,0 +1,25 @@
+/**************************************************************************************************
+**                                                                                               **
+**  文件名称:  single_instance.h                                                                 **
+**  版权所有:  CopyRight @ LEON WorkStudio CO.LTD. 2017                                          **
+**  文件描述:  判断系统中是否已经存在该进程的实例                                                **
+**  ===========================================================================================  **
+**  创建信息:  | 2017-9-14 | LEON | 创建本模块                                                   **
+**  ===========================================================================================  **
+**  修改信息:  单击此处添加....                                                                  **
+**************************************************************************************************/
+#ifndef SINGLE_INSTANCE_H
+#define SINGLE_INSTANCE_H
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+int proc_is_exist(const char *procname);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif

+ 107 - 0
双向链表/list.h

@@ -0,0 +1,107 @@
+#ifndef _LIST_HEAD_H
+#define _LIST_HEAD_H
+
+// 双向链表节点
+struct list_head {
+    struct list_head *next, *prev;
+};
+
+// 初始化节点:设置name节点的前继节点和后继节点都是指向name本身。
+#define LIST_HEAD_INIT(name) { &(name), &(name) }
+
+// 定义表头(节点):新建双向链表表头name,并设置name的前继节点和后继节点都是指向name本身。
+#define LIST_HEAD(name) \
+    struct list_head name = LIST_HEAD_INIT(name)
+
+// 初始化节点:将list节点的前继节点和后继节点都是指向list本身。
+static inline void INIT_LIST_HEAD(struct list_head *list)
+{
+    list->next = list;
+    list->prev = list;
+}
+
+// 添加节点:将new插入到prev和next之间。
+static inline void __list_add(struct list_head *new,
+                  struct list_head *prev,
+                  struct list_head *next)
+{
+    next->prev = new;
+    new->next = next;
+    new->prev = prev;
+    prev->next = new;
+}
+
+// 添加new节点:将new添加到head之后,是new称为head的后继节点。
+static inline void list_add(struct list_head *new, struct list_head *head)
+{
+    __list_add(new, head, head->next);
+}
+
+// 添加new节点:将new添加到head之前,即将new添加到双链表的末尾。
+static inline void list_add_tail(struct list_head *new, struct list_head *head)
+{
+    __list_add(new, head->prev, head);
+}
+
+// 从双链表中删除entry节点。
+static inline void __list_del(struct list_head * prev, struct list_head * next)
+{
+    next->prev = prev;
+    prev->next = next;
+}
+
+// 从双链表中删除entry节点。
+static inline void list_del(struct list_head *entry)
+{
+    __list_del(entry->prev, entry->next);
+}
+
+// 从双链表中删除entry节点。
+static inline void __list_del_entry(struct list_head *entry)
+{
+    __list_del(entry->prev, entry->next);
+}
+
+// 从双链表中删除entry节点,并将entry节点的前继节点和后继节点都指向entry本身。
+static inline void list_del_init(struct list_head *entry)
+{
+    __list_del_entry(entry);
+    INIT_LIST_HEAD(entry);
+}
+
+// 用new节点取代old节点
+static inline void list_replace(struct list_head *old,
+                struct list_head *new)
+{
+    new->next = old->next;
+    new->next->prev = new;
+    new->prev = old->prev;
+    new->prev->next = new;
+}
+
+// 双链表是否为空
+static inline int list_empty(const struct list_head *head)
+{
+    return head->next == head;
+}
+
+// 获取"MEMBER成员"在"结构体TYPE"中的位置偏移
+#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
+
+// 根据"结构体(type)变量"中的"域成员变量(member)的指针(ptr)"来获取指向整个结构体变量的指针
+#define container_of(ptr, type, member) ({          \
+    const typeof( ((type *)0)->member ) *__mptr = (ptr);    \
+    (type *)( (char *)__mptr - offsetof(type,member) );})
+
+// 遍历双向链表
+#define list_for_each(pos, head) \
+    for (pos = (head)->next; pos != (head); pos = pos->next)
+
+#define list_for_each_safe(pos, n, head) \
+    for (pos = (head)->next, n = pos->next; pos != (head); \
+        pos = n, n = pos->next)
+
+#define list_entry(ptr, type, member) \
+    container_of(ptr, type, member)
+
+#endif

+ 70 - 0
双向链表/test.c

@@ -0,0 +1,70 @@
+#include <stdio.h> 
+#include <stdlib.h>
+#include <string.h>
+#include "list.h" 
+
+struct person 
+{ 
+    int age; 
+    char name[20];
+    struct list_head list; 
+};
+
+void main(int argc, char* argv[]) 
+{ 
+    struct person *pperson; 
+    struct person person_head; 
+    struct list_head *pos, *next; 
+    int i;
+
+    // 初始化双链表的表头 
+    INIT_LIST_HEAD(&person_head.list); 
+
+    // 添加节点
+    for (i=0; i<5; i++)
+    {
+        pperson = (struct person*)malloc(sizeof(struct person));
+        pperson->age = (i+1)*10;
+        sprintf(pperson->name, "%d", i+1);
+        // 将节点链接到链表的末尾 
+        // 如果想把节点链接到链表的表头后面,则使用 list_add
+        list_add_tail(&(pperson->list), &(person_head.list));
+    }
+
+    // 遍历链表
+    printf("==== 1st iterator d-link ====\n"); 
+    list_for_each(pos, &person_head.list) 
+    { 
+        pperson = list_entry(pos, struct person, list); 
+        printf("name:%-2s, age:%d\n", pperson->name, pperson->age); 
+    } 
+
+    // 删除节点age为20的节点
+    printf("==== delete node(age:20) ====\n");
+    list_for_each_safe(pos, next, &person_head.list)
+    {
+        pperson = list_entry(pos, struct person, list);
+        if(pperson->age == 20)
+        {
+            list_del_init(pos);
+            free(pperson);
+        }
+    }
+
+    // 再次遍历链表
+    printf("==== 2nd iterator d-link ====\n");
+    list_for_each(pos, &person_head.list)
+    {
+        pperson = list_entry(pos, struct person, list);
+        printf("name:%-2s, age:%d\n", pperson->name, pperson->age);
+    }
+
+    // 释放资源
+    list_for_each_safe(pos, next, &person_head.list)
+    {
+        pperson = list_entry(pos, struct person, list); 
+        list_del_init(pos); 
+        free(pperson); 
+    }
+     
+}

+ 167 - 0
定时器任务/timer.c

@@ -0,0 +1,167 @@
+/**
+ *  应用定时器 模块
+ *  Author:Lzy
+ *  Greate Date:2012.10.20
+ */
+#include <stdio.h>
+#include <sys/ioctl.h>
+#include <string.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <signal.h>
+#include "timer.h"
+
+/**
+ * 函数功能:创建一个应用定时器,时间片为10ms的倍数。
+ * 本函数指定了定时器第一次定时时间和以后每次定时的时间,
+ * 如果在创建应用定时器后不是立即允许运行,则需要以后调用
+ * 控制应用定时器函数来激活定时器的运行
+ * pcName:不大于8字节字符串,应用定时器的名字
+ * ExpirationRoutine:定时器时间到时的处理函数
+ * ulID:定时器处理函数用到的参数,用来区分同一处理函数不同事件
+ * ulInitialTime:指定定时器初始化时间片
+ * ulRescheduleTime:指定在第一次时间片到后每次定时的时间片,0表示定时器仅执行一次
+ * uiEnable:4-->禁止应用定时器在创建完后运行,以后需要用ST_ControlTimer控制定时器运行
+ * :5-->允许应用定时器在创建完后运行
+ * phOSHandle( 出口):	 创建的应用定时器句柄
+ * 返回值:0x00------->创建成功
+ */
+unsigned int ST_CreateAppTimer(const char *pcName, void (*ExpirationRoutine)(int), unsigned long ulID, unsigned long ulInitialTime, unsigned long ulRescheduleTime, int uiEnable, int *phOSHandle)
+{
+	int timer_item;
+
+	if (uiEnable < 4 || uiEnable > 5)
+		return 0xFFFFFFFB;	// 禁止和允许参数错误
+
+	if (ulInitialTime == 0)
+		return 0xFFFFFFF3;	// 初始化时间片参数为0
+
+	for (timer_item = 0; timer_item < TIMERNUM; timer_item++)
+	{
+		if (hapi_timer[timer_item].id == 0)
+			break;
+	}
+
+	memcpy(&hapi_timer[timer_item].timer_name, pcName, strlen(pcName));
+	memset(&hapi_timer[timer_item].value, 0, sizeof(hapi_timer[timer_item].value));
+
+	hapi_timer[timer_item].value.it_value.tv_sec = 0;
+	hapi_timer[timer_item].value.it_value.tv_usec = 10000 * ulInitialTime;
+	hapi_timer[timer_item].value.it_interval.tv_sec = 0;
+	hapi_timer[timer_item].value.it_interval.tv_usec = ulRescheduleTime;
+
+	if (uiEnable == 4)
+	{
+		setitimer(ITIMER_REAL, &hapi_timer[timer_item].value, 0);
+		signal(SIGVTALRM, ExpirationRoutine);
+	}
+	else
+		signal(SIGVTALRM, ExpirationRoutine);
+
+	hapi_timer[timer_item].id = timer_item + 1;
+	*phOSHandle = timer_item + 1;
+
+	return 0;
+}
+
+/**
+ * 函数功能:删除指定的应用定时器
+ * phOSHandle( 入口):定时器句柄,由创建定时器函数获得
+ * phOSHandle( 出口):删除成功后被设置成EM_INVALID_HANDLE,失败则不改变原来值
+ *  返回值:0x00------->操作成功
+ */
+unsigned int ST_DeleteAppTimer(int *phOSHandle)
+{
+	int timer_item;
+
+	for (timer_item = 0; timer_item < TIMERNUM; timer_item++)
+	{
+		if (hapi_timer[timer_item].id == *phOSHandle)
+			break;
+	}
+
+	if (timer_item >= TIMERNUM)
+		return 0xFFFFFFDD;
+
+	memset(&hapi_timer[timer_item], 0, sizeof(&hapi_timer[timer_item]));
+	*phOSHandle = 0xFFFFFFE6;
+
+	return 0;
+}
+
+/**
+ * 函数功能:禁止或允许应用定时器运行,定时器是先前已经创建的
+ * hOSHandle:指定应用定时器的句柄
+ * uiEnable:---取值范围,EM_rtos_DISABLE_TIMER;实际值4,禁止应用定时器运行
+ * ---取值范围,EM_rtos_ENABLE_TIMER;实际值5,允许应用定时器运行
+ * 返回值:	0x00-->操作成功
+ */
+unsigned int ST_ControlAppTimer(int hOSHandle, unsigned int uiEnable)
+{
+	int timer_item;
+
+	for (timer_item = 0; timer_item < TIMERNUM; timer_item++)
+	{
+		if (hapi_timer[timer_item].id == hOSHandle)
+			break;
+	}
+
+	if (timer_item >= TIMERNUM)
+		return 0xFFFFFFE6;
+
+	if (uiEnable < 4 || uiEnable > 5)
+		return 0xFFFFFFFB;
+
+	if (uiEnable == 4)
+	{
+		setitimer(ITIMER_REAL, &hapi_timer[timer_item].value, 0);
+	}
+
+	return 0;
+}
+
+/**
+ * 函数功能:重新设置定时器,包括定时器处理程序,首次和以后时间,是否允许立即运行
+ * hOSHandle:定时器句柄,由创建定时器函数获得
+ * ExpirationRoutine:定时器时间到时的处理函数
+ * ulInitialTime:指定定时器初始化时间片
+ * ulRescheduleTime:指定在第一次时间片到后每次定时的时间片,0表示定时器仅执行一次
+ *  uiEnable: 4-->禁止应用定时器在重新设置完后运行,以后需要用ST_ControlTimer控制定时器运行
+ *  : 5-->允许应用定时器在重新设置完后运行
+ *  返回值:0x00------->创建成功
+ */
+unsigned int ST_ResetAppTimer(int hOSHandle, void (*ExpirationRoutine)(int), unsigned long ulInitialTime, unsigned long ulRescheduleTime, unsigned int uiEnable)
+{
+	int timer_item;
+
+	if (uiEnable < 4 || uiEnable > 5)
+		return 0xFFFFFFFB;
+	if (ulInitialTime == 0)
+		return 0xFFFFFFF3;
+
+	for (timer_item = 0; timer_item < TIMERNUM; timer_item++)
+	{
+		if (hapi_timer[timer_item].id == hOSHandle)
+			break;
+	}
+
+	memset(&hapi_timer[timer_item].value, 0, sizeof(&hapi_timer[timer_item].value));
+	hapi_timer[timer_item].value.it_value.tv_sec = 0;
+	hapi_timer[timer_item].value.it_value.tv_usec = 10000 * ulInitialTime;
+	hapi_timer[timer_item].value.it_interval.tv_sec = 0;
+	hapi_timer[timer_item].value.it_interval.tv_usec = ulRescheduleTime;
+
+	if (uiEnable == 4)
+	{
+		setitimer(ITIMER_REAL, &hapi_timer[timer_item].value, 0);
+		signal(SIGVTALRM, ExpirationRoutine);
+	}
+	else
+		signal(SIGVTALRM, ExpirationRoutine);
+
+	return 0;
+
+}
+

+ 36 - 0
定时器任务/timer.h

@@ -0,0 +1,36 @@
+#ifndef _TIMER_H_
+#define _TIMER_H_
+
+#define TIMERNUM	6
+
+typedef struct
+{
+  char id;
+  struct itimerval value;
+  char timer_name[10];
+}timer;
+
+timer hapi_timer[TIMERNUM];
+
+enum
+{
+	IOCTL_TIMERINIT =5,
+	IOCTL_TIMERSET, //set value
+	IOCTL_STATEGATE,//get value
+	IOCTL_TIMEDEL,
+};
+
+typedef struct
+{
+	int id;//TIMERºÅ
+	int data;//TIMER³õʼֵ
+	int timer_flag;
+} sep_timer;
+
+
+#define STEP_TIMER   2
+#define HEAD_TIMER  3
+#define PFSTEP_TIMER  1
+#define CLOCK_TIMER   4
+
+#endif

+ 57 - 0
日志文件/commLOG.c

@@ -0,0 +1,57 @@
+#include "commLOG.h"
+
+//日志的编号
+int giInfoNumb = 1;
+int debugInfo(char *pLogPath, char *pFile, const char *pFuncName, int iLineNumb, char *fmt, ...)
+{
+    if(NULL == pLogPath ||'\0' == pLogPath[0] || NULL == pFile || '\0' == pFile[0] || NULL == pFuncName ||'\0' == pFuncName[0]){
+		printf("debugInfo param err:%s,%s,%s,%d\r\n", pLogPath, pFile, pFuncName, iLineNumb);
+        return LOG_VS_ERR;
+	}
+    //判断文件大小是否清空该文件,每1000次写日志里检测1次文件大小
+    if(0 == (giInfoNumb % 10))
+    {
+        struct stat fileStat;
+        if((giInfoNumb >= LOG_LINE_MAX) || ((0 == stat(pLogPath, &fileStat)) && (fileStat.st_size > LOG_SIZE_MAX))){
+			printf("\ndebugInfo log too big,%dline,%dbyte\n", giInfoNumb, (int)fileStat.st_size);
+            remove(pLogPath);
+			giInfoNumb = 0;
+		}
+    }
+
+    //写入日期、函数信息
+    time_t timeSecs = time(NULL);
+    struct tm *timeInfo = localtime(&timeSecs);
+    char acTitle[LOG_STR_LEN_1024] = { 0 };
+	char debugMsg[LOG_STR_LEN_512] = { 0 };
+	
+    va_list args;
+    va_start(args, fmt);
+    vsnprintf(debugMsg, sizeof(debugMsg), fmt, args);
+    va_end(args);
+#if 0    
+    snprintf(acTitle, sizeof(acTitle), "[%04d] [%d%02d%02d/%02d:%02d:%02d] [%s] [%s:%d] %s\n", giInfoNumb++,
+             timeInfo->tm_year + 1900, timeInfo->tm_mon + 1, timeInfo->tm_mday, 
+             timeInfo->tm_hour, timeInfo->tm_min, timeInfo->tm_sec, pFile, pFuncName, iLineNumb,
+			 acTitle);
+#else	
+	//节约空间
+    snprintf(acTitle, sizeof(acTitle), "%02d %02d/%02d:%02d:%02d %s\n", giInfoNumb++,
+            timeInfo->tm_mday,timeInfo->tm_hour, timeInfo->tm_min, timeInfo->tm_sec,
+			debugMsg); 
+#endif
+	//调试打印
+	printf(acTitle);
+
+    //打开文件,写入日志
+    FILE *pLogHandle = fopen(pLogPath, "a+");
+    if(NULL == pLogHandle){
+		printf("ERROR,debugInfo:fopen=%s\n",strerror(errno));
+        return LOG_VS_ERR;
+	}
+    int iLen = strlen(acTitle);
+    fwrite(acTitle, iLen, 1, pLogHandle);
+	fclose(pLogHandle);
+    
+    return LOG_VS_OK;
+}

+ 34 - 0
日志文件/commLOG.h

@@ -0,0 +1,34 @@
+#ifndef _commLOG_H_
+#define _commLOG_H_ 
+ 
+#include <stdio.h>
+#include <string.h> 
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>  
+#include <stdarg.h> 
+#include <time.h>
+#include <assert.h>
+#include <errno.h>
+
+#define LOG_SIZE_MAX           4096 	//16777216             //1024*1024*16=16M
+#define LOG_LINE_MAX           120  	//1000
+#define LOG_FILE_PATH          "/root/door-ctrl/log-door-ctrl"        //日志文件路径
+#define LOG_PARAMS             LOG_FILE_PATH,__FILE__,__func__,__LINE__ //日志文件路径 调用函数所在文件 调用函数名 调用debugInfo时所在行号
+
+//显示调用debugInfo接口的函数所在的文件名、函数名、行号
+//调用举例:  debuInfo(LOG_PARAMS, “some string %s, some int %d and so on", "hello log", 101);
+
+#if 1
+int debugInfo(char *pLogPath, char *pFile, const char *pFuncName, int iLineNumb, char *fmt, ...);
+#define DBGLog(fmt, args...) debugInfo(LOG_PARAMS, fmt, ##args) 
+#else
+#define DBGLog(fmt, args...) do{}while(0)
+#endif
+ 
+#define LOG_VS_ERR 0
+#define LOG_VS_OK  1
+#define LOG_STR_LEN_1024 1024
+#define LOG_STR_LEN_512  512
+
+#endif

+ 56 - 0
日志文件/commMsgQueue.c

@@ -0,0 +1,56 @@
+#include "commMsgQueue.h"
+static int commMsgQueue(int flags)
+{
+    key_t _key = ftok(PATHNAME,PROJ_ID);//ftok参数有两个,第一个是路径变量,第二个是projectID
+    if(_key < 0){
+        perror("ftok");
+        return -1;
+    }
+    int msgid = msgget(_key,flags);
+    if(msgid < 0){
+        perror("msgget");
+        return -2;
+    }
+    return msgid;
+}
+ 
+int creatMsgQueue()
+{
+    return commMsgQueue(IPC_CREAT | IPC_EXCL|0666);
+}
+ 
+int getMsgQueue()
+{   
+    return commMsgQueue(IPC_CREAT);
+}
+ 
+int destroyMsgQueue(int msgid)
+{
+    if(msgctl(msgid, IPC_RMID, NULL) < 0){
+        perror("msgctl");
+        return -1;
+    }
+    return 0;
+}
+int sendMsg(int msgid, int type, const char *msg)
+{
+    struct msgbuf _mb;
+    _mb.mtype = type;
+    strcpy(_mb.mtext,msg);
+    if(msgsnd(msgid, &_mb,sizeof(_mb.mtext),0)<0){
+        perror("msgsnd");
+        return -1;
+    }
+    return 0;
+}
+int recvMsg(int msgid, int type, char *out)
+{
+    struct msgbuf _mb;
+    if(msgrcv(msgid, &_mb, sizeof(_mb.mtext),type,IPC_NOWAIT)<0){	//0.阻塞 IPC_NOWAIT.非阻塞
+        //perror("msgrcv");
+        return -1;
+    }
+ 
+    strcpy(out,_mb.mtext);
+    return 0;
+}

+ 34 - 0
日志文件/commMsgQueue.h

@@ -0,0 +1,34 @@
+#ifndef _commMsgQueue_H_
+#define _commMsgQueue_H_ 
+ 
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/ipc.h>
+#include <sys/msg.h>
+#include <string.h>
+ 
+#define PATHNAME "."
+#define PROJ_ID 0x0824
+
+enum{
+	QUEUE_MSG_CLIENT,		//客户端
+	QUEUE_MSG_POST,			//网页端
+	QUEUE_MSG_UNLOCK,		//开锁
+	QUEUE_MSG_MAX			//最大
+};
+
+ 
+struct msgbuf{
+    long mtype;
+    char mtext[1024];
+};
+int creatMsgQueue();
+int getMsgQueue();
+int destroyMsgQueue(int msgid);
+int sendMsg(int msgid, int type, const char *msg);
+int recvMsg(int msgid, int type, char *out);
+ 
+ 
+ 
+ 
+#endif

+ 146 - 0
日志文件/log.c

@@ -0,0 +1,146 @@
+/*************************************************************************
+    > File Name: log.c
+    > Author: 
+ ************************************************************************/
+#include <stdio.h>
+#include <sys/types.h> 
+#include <unistd.h> 
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <stdarg.h>
+#include <time.h>
+#include <pthread.h>
+
+int safe_asprintf(char **strp, const char *fmt, ...);
+int safe_vasprintf(char **strp, const char *fmt, va_list ap);
+void plog(const char *format, ...) ;
+void pinfo(const char *format, ...) ;
+
+#define DEBUG
+
+#ifdef DEBUG
+void plog(const char *format, ...);
+void pinfo(const char *format, ...);
+#define debug(fmt, args...) plog(fmt, ##args) 
+#else
+#define debug(fmt, args...) do{}while(0)
+#endif
+
+static pthread_mutex_t fileMutex = PTHREAD_MUTEX_INITIALIZER;
+
+int main(int argc, char *argv)
+{
+    return 0;
+}
+
+/*
+ * safe_asprintf();
+ */
+int safe_asprintf(char **strp, const char *fmt, ...) 
+{
+    va_list ap;
+    int retval;
+
+    va_start(ap, fmt);
+    retval = safe_vasprintf(strp, fmt, ap);
+    va_end(ap);
+
+    return retval;
+}
+
+/*
+ * safe_vasprintf();
+ */
+int safe_vasprintf(char **strp, const char *fmt, va_list ap) 
+{
+    int retval;
+
+    retval = vasprintf(strp, fmt, ap);
+    if (retval == -1) 
+    {
+        printf("Failed to vasprintf: %s.  Bailing out\n", strerror(errno));
+        return 1;
+    }
+    return retval;
+}
+
+/*
+ * plog();
+ */
+void plog(const char *format, ...) 
+{
+
+    pthread_mutex_lock(&fileMutex);
+
+    FILE *fp = NULL;
+    va_list vlist;
+    char *fmt = NULL;
+
+    // Open debug info output file.
+    if (!(fp = fopen("log.txt", "a+"))) {
+        pthread_mutex_unlock(&fileMutex);
+        return;
+    }
+
+    va_start(vlist, format);
+    safe_vasprintf(&fmt, format, vlist);
+    va_end(vlist);
+    if (!fmt) {
+        pthread_mutex_unlock(&fileMutex);
+        return;
+    }
+
+    time_t timep;
+    struct tm *ptm = NULL;
+    time(&timep);
+    ptm = localtime(&timep);
+    fprintf(fp, "[%04d-%02d-%02d-%02d-%02d-%02d] %s", 
+            ptm->tm_year + 1900, 
+            ptm->tm_mon + 1,
+            ptm->tm_mday, 
+            ptm->tm_hour, 
+            ptm->tm_min, 
+            ptm->tm_sec, 
+            fmt);
+
+    free(fmt);
+    fsync(fileno(fp));
+    fclose(fp);
+
+    pthread_mutex_unlock(&fileMutex);
+}
+
+/*
+ * pinfo();
+ */
+void pinfo(const char *format, ...) 
+{
+    pthread_mutex_lock(&fileMutex);
+
+    FILE *fp = NULL;
+    va_list vlist;
+    char *fmt = NULL;
+
+    // Open debug info output file.
+    if (!(fp = fopen("log.txt", "a+"))) {
+        pthread_mutex_unlock(&fileMutex);
+        return;
+    }
+
+    va_start(vlist, format);
+    safe_vasprintf(&fmt, format, vlist);
+    va_end(vlist);
+    if (!fmt) {
+        pthread_mutex_unlock(&fileMutex);
+        return;
+    }
+
+    fprintf(fp, "%s", fmt);
+
+    free(fmt);
+    fsync(fileno(fp));
+    fclose(fp);
+
+    pthread_mutex_unlock(&fileMutex);
+}

+ 70 - 0
日志文件/mylog.c

@@ -0,0 +1,70 @@
+#define SIZE_MAX               2048 //16777216             //1024*1024*16=16M
+#define LINE_MAX               100  //1000
+#define LOG_FILE_PATH          "./mylog.txt"        //日志文件路径
+//#define LOG_PARAMS             LOG_FILE_PATH,__FILE__,__func__,__LINE__ //日志文件路径 调用函数所在文件 调用函数名 调用debugInfo时所在行号
+
+#define LOG_PARAMS             LOG_FILE_PATH,"","","" 
+//显示调用debugInfo接口的函数所在的文件名、函数名、行号
+//调用举例:  debuInfo(LOG_PARAMS, “some string %s, some int %d and so on", "hello log", 101);
+
+#define DEBUG
+#ifdef DEBUG
+int debugInfo(char *pLogPath, char *pFile, const char *pFuncName, int iLineNumb, char *fmt, ...);
+#define DBGLog(fmt, args...) debugInfo(LOG_PARAMS, fmt, ##args) 
+#else
+#define DBGLog(fmt, args...) do{}while(0)
+#endif
+
+unsigned int curr_log_change_flag = 0;
+unsigned int last_log_change_flag = 0;
+unsigned char log_change_busy = 0;
+
+//日志的编号
+int giInfoNumb = 1;
+int debugInfo(char *pLogPath, char *pFile, const char *pFuncName, int iLineNumb, char *fmt, ...)
+{
+    if(NULL == pLogPath ||'\0' == pLogPath[0] || NULL == pFile || '\0' == pFile[0] || NULL == pFuncName ||'\0' == pFuncName[0])
+        return VS_ERR;
+    //判断文件大小是否清空该文件,每1000次写日志里检测1次文件大小
+    if(0 == (giInfoNumb % LINE_MAX))
+    {
+        struct stat fileStat;
+        if(0 == stat(pLogPath, &fileStat) && fileStat.st_size > SIZE_MAX)
+            remove(pLogPath);
+    }
+    //打开文件,写入日志
+    FILE *pLogHandle = fopen(pLogPath, "a+");
+    if(NULL == pLogHandle)
+        return VS_ERR;
+    log_change_busy = 1;
+    //写入日期、函数信息
+    time_t timeSecs = time(NULL);
+    struct tm *timeInfo = localtime(&timeSecs);
+    char acTitle[STR_LEN_2048] = { 0 };
+#if 0    
+    snprintf(acTitle, sizeof(acTitle), "[%04d] [%d%02d%02d/%02d:%02d:%02d] [%s] [%s:%d]\n", giInfoNumb++,
+             timeInfo->tm_year + 1900, timeInfo->tm_mon + 1, timeInfo->tm_mday, 
+             timeInfo->tm_hour, timeInfo->tm_min, timeInfo->tm_sec, pFile, pFuncName, iLineNumb);
+#else
+    snprintf(acTitle, sizeof(acTitle), "[%03d] [%d%02d%02d/%02d:%02d:%02d] ", giInfoNumb++,
+            timeInfo->tm_year + 1900, timeInfo->tm_mon + 1, timeInfo->tm_mday, 
+            timeInfo->tm_hour, timeInfo->tm_min, timeInfo->tm_sec); 
+#endif
+    int iLen = strlen(acTitle);
+    fwrite(acTitle, iLen, 1, pLogHandle);
+    //写入日志
+    //fwrite("\t\t\t", 3, 1, pLogHandle);
+    memset(acTitle, 0, sizeof(acTitle));
+    va_list args;
+    va_start(args, fmt);
+    vsnprintf(acTitle, sizeof(acTitle), fmt, args);
+    va_end(args);
+    iLen = strlen(acTitle);
+    fwrite(acTitle, iLen, 1, pLogHandle);
+    fwrite("\n", 1, 1, pLogHandle);
+    //关闭日志文件
+    fclose(pLogHandle);
+    curr_log_change_flag++;
+	log_change_busy = 0;
+    return VS_OK;
+}

+ 30 - 0
消息队列/说明.txt

@@ -0,0 +1,30 @@
+
+消息队列的函数定义如下:
+#include <sys/msg.h>
+
+int msgctl(int msqid, int cmd, struct msqid_ds *buf);
+int msgget(key_t key, int msgflg);
+int msgrcv(int msqid, void *msg_ptr, size_t msg_sz, long int msgtype, int msgflg);
+int msgsnd(int msqid, const void *msg_ptr, size_t msg_sz, int msgflg);
+
+Linux系统中有两个宏定义:
+ MSGMAX, 以字节为单位,定义了一条消息的最大长度。
+ MSGMNB, 以字节为单位,定义了一个队列的最大长度。
+
+
+struct my_msg_st {
+  long int my_msg_type;
+  char some_text[BUFSIZ];
+}some_data;
+
+创建
+if (msgid = msgget((key_t)1234, 0666 | IPC_CREAT)) == -1) 
+
+接收
+if (msgrcv(msgid, (void *)&some_data, BUFSIZ, msg_to_receive, 0) == -1) 
+
+发送
+if (msgsnd(msgid, (void *)&some_data, MAX_TEXT, 0) == -1) 
+
+删除
+if (msgctl(msgid, IPC_RMID, 0) == -1)