源码目录结构
.
.
├── cfg
│ └── conf.json
├── inc
│ ├── parson.h
│ └── ssh.h
├── Makefile
└── src
├── main.c
├── parson.c
└── ssh.c
源码
main.c
#include <stdio.h>
#include<pthread.h>
#include <signal.h>
#include <stdlib.h> /*exit*/
#include <unistd.h> /*access*/
#include <string.h>
#include <sys/prctl.h>
#include "parson.h"
#include "ssh.h"
#define LOG_ERR 0
#define LOG_WARN 1
#define LOG_INFO 2
static int debug_level=LOG_INFO;
#define DEBUG(level, fmt, args...) do{ \
if(level <= debug_level) \
fprintf(stderr, "%s:%s:%d:"fmt, __FILE__, __FUNCTION__, __LINE__, ##args); \
}while(0)
static int exit_sig = 0;
static int quit_sig = 0;
static void sig_handler(int sigio)
{
if (sigio == SIGQUIT) {
quit_sig = 1;;
} else if ((sigio == SIGINT) || (sigio == SIGTERM)) {
exit_sig = 1;
}
}
typedef struct{
/*ssh:0 off ssh:1 on*/
int ssh;
} act_t;
act_t action;
typedef struct{
int (*fun)(void);
} fun_t;
fun_t function;
static int count=0;
static pthread_mutex_t mx_count = PTHREAD_MUTEX_INITIALIZER;
void thread_sub(void){
prctl(PR_SET_NAME, "third_sub");
while(!exit_sig || !quit_sig){
DEBUG(LOG_INFO, "this is thread_sub, count=%d\n", count);
pthread_mutex_lock(&mx_count);
count--;
pthread_mutex_unlock(&mx_count);
DEBUG(LOG_INFO, "this is thread_sub, count=%d\n", count);
sleep(2);
}
}
void thread_add(void){
prctl(PR_SET_NAME, "third_add");
while(!exit_sig && !quit_sig){
DEBUG(LOG_INFO, "this is thread_add, count=%d\n", count);
pthread_mutex_lock(&mx_count);
count++;
DEBUG(LOG_INFO, "this is thread_add, count=%d\n", count);
pthread_mutex_unlock(&mx_count);
sleep(2);
}
}
static int parse_conf(const char * conf_file)
{
const char conf_obj[] = "action";
char param_name[32]; /* used to generate variable parameter names */
const char *str; /* used to store string value from JSON object */
JSON_Value *root_val;
JSON_Object *root = NULL;
JSON_Object *conf = NULL;
JSON_Object *child_conf = NULL;
//JSON_Value *val;
/* try to parse JSON */
root_val = json_parse_file_with_comments(conf_file);
root = json_value_get_object(root_val);
if (root == NULL) {
DEBUG(LOG_ERR, "ERROR: %s is not a valid JSON file\n", conf_file);
exit(EXIT_FAILURE);
}
memset(&action, 0, sizeof(act_t));
conf = json_object_get_object(root, conf_obj);
if (conf == NULL) {
DEBUG(LOG_ERR, "INFO: %s does not contain a JSON object named %s\n", conf_file, conf_obj);
return -1;
} else {
DEBUG(LOG_INFO, "INFO: %s does contain a JSON object named %s\n", conf_file, conf_obj);
snprintf(param_name, sizeof(param_name), "ssh");
action.ssh = (int)json_object_dotget_number(conf, param_name);
DEBUG(LOG_INFO, "INFO: ssh is %d\n", action.ssh);
if(action.ssh){
function.fun=ssh_on;
DEBUG(LOG_INFO, "INFO: fun.ssh:%p ssh:%p\n", function.fun, ssh_on);
}
else
function.fun=ssh_off;
}
json_value_free(root_val);
return 0;
}
int main(int argc, char *argv[]){
pthread_t sub_thrid;
pthread_t add_thrid;
int thread_ret=-1;
const char conf_file[]="conf.json";
prctl(PR_SET_NAME, "fun_main");
struct sigaction sigact;
sigemptyset(&sigact.sa_mask);
sigact.sa_flags = 0;
sigact.sa_handler = sig_handler;
sigaction(SIGQUIT, &sigact, NULL); /* Ctrl-\ */
sigaction(SIGINT, &sigact, NULL); /* Ctrl-C */
sigaction(SIGTERM, &sigact, NULL); /* default "kill" command */
if (access(conf_file, R_OK) == 0) {
DEBUG(LOG_INFO, "INFO: found debug configuration file %s, other configuration files will be ignored\n", conf_file);
parse_conf(conf_file);
}else{
DEBUG(LOG_ERR, "ERROR: failed to find any configuration file named %s\n", conf_file);
exit(EXIT_FAILURE);
}
thread_ret = pthread_create( &sub_thrid, NULL, (void * (*)(void *))thread_sub, NULL);
if(thread_ret != 0){
DEBUG(LOG_ERR, "create thread_sub failed\n");
exit(EXIT_FAILURE);
}
thread_ret = pthread_create( &add_thrid, NULL, (void * (*)(void *))thread_add, NULL);
if(thread_ret != 0){
DEBUG(LOG_ERR, "create thread_pub failed\n");
exit(EXIT_FAILURE);
}
while(!exit_sig && !quit_sig){
DEBUG(LOG_INFO, "INFO2: fun:%p \n", function.fun);
function.fun();
sleep(2);
}
thread_ret = pthread_cancel(sub_thrid);
if(thread_ret != 0){
DEBUG(LOG_ERR, "cancel thread_sub failed\n");
exit(EXIT_FAILURE);
}
thread_ret = pthread_cancel(add_thrid);
if(thread_ret != 0){
DEBUG(LOG_ERR, "cancel thread_add failed\n");
exit(EXIT_FAILURE);
}
DEBUG(LOG_INFO, "exit fun_main process success\n");
exit(EXIT_SUCCESS);
}
ssh.c
#include <stdio.h>
#include "ssh.h"
int ssh_on(void){
printf("this is ssh on func\n");
}
int ssh_off(void){
printf("this is ssh off func\n");
}
ssh.h
#ifndef _SSH_H_
#define _SSH_H_
extern int ssh_on(void);
extern int ssh_off(void);
#endif
conf.json
{
"action": {
"ssh": 0
}
}
Makefile
SRC=$(wildcard ./src/*.c)
OBJ=$(patsubst %.c, %.o, $(SRC))
TAR=./tar/fun
INC=./inc
all:$(TAR)
$(TAR):$(OBJ)
$(CC) $(CFLAGS) -I$(INC) -o $@ $^ -lpthread
%.o:%.c
@if ! [ -d ./tar ];then \
mkdir -p tar; \
fi;
@cp ./cfg/conf.json ./tar/conf.json
$(CC) $(CFLAGS) -I$(INC) -o $@ -c $<
.PHONY:clean
clean:
rm -rf ./tar src/*.o
执行结构
查看线程
cecport@ubuntu:~/training/pthread_parse_callback/tar$ ps -T
PID SPID TTY TIME CMD
6007 6007 pts/3 00:00:04 bash
28328 28328 pts/3 00:00:00 fun_main
28328 28329 pts/3 00:00:00 third_sub
28328 28330 pts/3 00:00:00 third_add
28332 28332 pts/3 00:00:00 ps
查看执行结果
cecport@ubuntu:~/training/pthread_parse_callback/tar$ ./fun
src/main.c:main:127:INFO: found debug configuration file conf.json, other configuration files will be ignored
src/main.c:parse_conf:95:INFO: conf.json does contain a JSON object named action
src/main.c:parse_conf:98:INFO: ssh is 0
src/main.c:main:146:INFO2: fun:0x406705
this is ssh off func
src/main.c:thread_add:59:this is thread_add, count=0
src/main.c:thread_add:62:this is thread_add, count=1
src/main.c:thread_sub:48:this is thread_sub, count=1
src/main.c:thread_sub:52:this is thread_sub, count=0
src/main.c:main:146:INFO2: fun:0x406705
this is ssh off func
src/main.c:thread_add:59:this is thread_add, count=0
src/main.c:thread_add:62:this is thread_add, count=1
src/main.c:thread_sub:48:this is thread_sub, count=1
src/main.c:thread_sub:52:this is thread_sub, count=0