add one ping sample which can ping any host in fiber mode

This commit is contained in:
ubuntu14 2016-08-05 23:21:51 +08:00
parent 271fc96cdf
commit 3c8dc7b019
9 changed files with 170 additions and 46 deletions

View File

@ -17,7 +17,7 @@ static errno_fn __sys_errno = NULL;
static fcntl_fn __sys_fcntl = NULL;
typedef struct {
ACL_RING queue; /* ready fiber queue */
ACL_RING ready; /* ready fiber queue */
ACL_RING dead; /* dead fiber queue */
ACL_FIBER **fibers;
size_t size;
@ -28,9 +28,6 @@ typedef struct {
size_t idgen;
int count;
int switched;
#ifdef USE_DBUF
ACL_DBUF_POOL *dbuf;
#endif
} FIBER_TLS;
static FIBER_TLS *__main_fiber = NULL;
@ -51,10 +48,6 @@ static void thread_free(void *ctx)
if (__thread_fiber == NULL)
return;
#ifdef USE_DBUF
acl_dbuf_pool_destroy(tf->dbuf);
#endif
if (tf->fibers)
acl_myfree(tf->fibers);
acl_myfree(tf);
@ -92,11 +85,8 @@ static void fiber_check(void)
__thread_fiber->size = 0;
__thread_fiber->idgen = 0;
__thread_fiber->count = 0;
#ifdef USE_DBUF
__thread_fiber->dbuf = acl_dbuf_pool_create(640000);
#endif
acl_ring_init(&__thread_fiber->queue);
acl_ring_init(&__thread_fiber->ready);
acl_ring_init(&__thread_fiber->dead);
if ((unsigned long) acl_pthread_self() == acl_main_thread_self()) {
@ -219,14 +209,14 @@ void fiber_exit(int exit_code)
void acl_fiber_ready(ACL_FIBER *fiber)
{
fiber->status = FIBER_STATUS_READY;
acl_ring_prepend(&__thread_fiber->queue, &fiber->me);
acl_ring_prepend(&__thread_fiber->ready, &fiber->me);
}
int acl_fiber_yield(void)
{
int n;
if (acl_ring_size(&__thread_fiber->queue) == 0)
if (acl_ring_size(&__thread_fiber->ready) == 0)
return 0;
n = __thread_fiber->switched;
@ -273,12 +263,8 @@ static void fiber_start(unsigned int x, unsigned int y)
static void fiber_free(FIBER_TLS *tls, ACL_FIBER *fiber)
{
#ifdef USE_DBUF
acl_dbuf_pool_free(tls->dbuf, fiber);
#else
(void) tls;
acl_myfree(fiber);
#endif
}
static ACL_FIBER *fiber_alloc(void (*fn)(ACL_FIBER *, void *),
@ -306,20 +292,10 @@ static ACL_FIBER *fiber_alloc(void (*fn)(ACL_FIBER *, void *),
head = acl_ring_pop_head(&__thread_fiber->dead);
if (head == NULL)
#ifdef USE_DBUF
fiber = (ACL_FIBER *) acl_dbuf_pool_calloc(
__thread_fiber->dbuf, sizeof(ACL_FIBER) + size);
#else
fiber = (ACL_FIBER *) acl_mycalloc(1, sizeof(ACL_FIBER) + size);
#endif
else if ((fiber = ACL_RING_TO_APPL(head, ACL_FIBER, me))->size < size) {
fiber_free(__thread_fiber, fiber);
#ifdef USE_DBUF
fiber = (ACL_FIBER *) acl_dbuf_pool_calloc(
__thread_fiber->dbuf, sizeof(ACL_FIBER) + size);
#else
fiber = (ACL_FIBER *) acl_mycalloc(1, sizeof(ACL_FIBER) + size);
#endif
} else
size = fiber->size;
@ -414,7 +390,7 @@ void acl_fiber_schedule(void)
acl_fiber_hook_api(1);
for (;;) {
head = acl_ring_pop_head(&__thread_fiber->queue);
head = acl_ring_pop_head(&__thread_fiber->ready);
if (head == NULL) {
acl_msg_info("------- NO ACL_FIBER NOW --------");
break;
@ -476,7 +452,7 @@ void acl_fiber_switch(void)
acl_ring_append(&__thread_fiber->dead, &current->me);
}
head = acl_ring_pop_head(&__thread_fiber->queue);
head = acl_ring_pop_head(&__thread_fiber->ready);
if (head == NULL) {
fiber_swap(current, &__thread_fiber->schedule);

View File

@ -12,6 +12,7 @@
#include <sys/stat.h>
#include "fiber.h"
typedef unsigned int (*sleep_fn)(unsigned int seconds);
typedef int (*pipe_fn)(int pipefd[2]);
#ifdef HAS_PIPE2
typedef int (*pipe2_fn)(int pipefd[2], int flags);
@ -32,6 +33,7 @@ typedef ssize_t (*sendto_fn)(int, const void *, size_t, int,
const struct sockaddr *, socklen_t);
typedef ssize_t (*sendmsg_fn)(int, const struct msghdr *, int);
static sleep_fn __sys_sleep = NULL;
static pipe_fn __sys_pipe = NULL;
#ifdef HAS_PIPE2
static pipe2_fn __sys_pipe2 = NULL;
@ -60,6 +62,7 @@ void hook_io(void)
__called++;
__sys_sleep = (sleep_fn) dlsym(RTLD_NEXT, "sleep");
__sys_pipe = (pipe_fn) dlsym(RTLD_NEXT, "pipe");
#ifdef HAS_PIPE2
__sys_pipe2 = (pipe2_fn) dlsym(RTLD_NEXT, "pipe2");
@ -80,6 +83,14 @@ void hook_io(void)
__sys_sendmsg = (sendmsg_fn) dlsym(RTLD_NEXT, "sendmsg");
}
unsigned int sleep(unsigned int seconds)
{
if (!acl_var_hook_sys_api)
return __sys_sleep(seconds);
return acl_fiber_sleep(seconds);
}
int pipe(int pipefd[2])
{
int ret = __sys_pipe(pipefd);

View File

@ -848,28 +848,34 @@ int gethostbyname_r(const char *name, struct hostent *ret,
acl_foreach(iter, res) {
ACL_HOSTNAME *h = (ACL_HOSTNAME*) iter.data;
struct in_addr addr;
len = strlen(h->ip);
len = sizeof(struct in_addr);
n += len;
memcpy(buf, h->ip, len);
buf[len] = 0;
if (n > buflen)
break;
memset(&addr, 0, sizeof(addr));
addr.s_addr = inet_addr(h->ip);
memcpy(buf, &addr, len);
if (i >= MAX_COUNT)
break;
ret->h_addr_list[i++] = buf;
buf += len + 1;
buf += len;
ret->h_length += len;
}
if (i == 0) {
acl_msg_error("%s(%d), %s: i == 0",
__FILE__, __LINE__, __FUNCTION__);
if (h_errnop)
*h_errnop = ERANGE;
RETURN (-1);
if (i > 0) {
*result = ret;
RETURN (0);
}
*result = ret;
acl_msg_error("%s(%d), %s: i == 0, n: %d, buflen: %d",
__FILE__, __LINE__, __FUNCTION__, (int) n, (int) buflen);
RETURN (0);
if (h_errnop)
*h_errnop = ERANGE;
RETURN (-1);
}

View File

@ -1,4 +1,11 @@
17) 2016.8.5
17.1) feature: hook_io.c 中增加系统 API sleep 的 hook 函数
16) 2016.8.4
16.1) bugfix: hook_net.c 中的 gethostbyname_r 在解析域名时的地址所用字节序有误
--- found by 陈晓勇
15) 2016.7.28
15.1) bugfix: hook_net.c 中的 poll/epoll_wait 对于超时的计数有误,会导致超时
时间提前

View File

@ -100,13 +100,18 @@ ACL_PATH = ../../../lib_acl
ACL_INC = $(ACL_PATH)/include
ACL_LIB = $(ACL_PATH)/lib
PRO_PATH = ../../../lib_protocol
PRO_INC = $(PRO_PATH)/include
PRO_LIB = $(PRO_PATH)/lib
FIBER_PATH = ../../../lib_fiber
FIBER_INC = $(FIBER_PATH)/c/include
FIBER_LIB = $(FIBER_PATH)/lib
EXTLIBS =
CFLAGS += -I.. -I$(ACL_INC) -I$(FIBER_INC)
LDFLAGS = -L$(ACL_LIB) -L$(FIBER_LIB) -l_fiber -l_acl $(EXTLIBS) $(SYSLIB)
CFLAGS += -I.. -I$(PRO_INC) -I$(ACL_INC) -I$(FIBER_INC)
LDFLAGS = -L$(PRO_LIB) -l_protocol -L$(FIBER_LIB) -l_fiber \
-L$(ACL_LIB) -l_acl $(EXTLIBS) $(SYSLIB)
###########################################################

View File

@ -0,0 +1,2 @@
include ../Makefile.in
PROG = ping

View File

@ -0,0 +1,110 @@
#include "lib_acl.h"
#include "lib_protocol.h"
#include "fiber/lib_fiber.h"
#include <signal.h>
static int __nfibers = 0;
static int __npkt = 10;
static void display_res(ICMP_CHAT *chat)
{
if (chat) {
/* 显示 PING 的结果总结 */
icmp_stat(chat);
printf(">>>max pkts: %d\r\n", icmp_chat_seqno(chat));
}
}
/* PING 线程入口 */
static void fiber_ping(ACL_FIBER *fiber acl_unused, void *arg)
{
const char *dest = (const char *) arg;
ACL_DNS_DB* dns_db;
const char *ip;
int delay = 1; /* 发送 ping 包的时间间隔(秒)*/
ICMP_CHAT *chat;
/* 通过域名解析出IP地址 */
dns_db = acl_gethostbyname(dest, NULL);
if (dns_db == NULL) {
acl_msg_warn("Can't find domain %s", dest);
return;
}
/* 只取出域名第一个 IP 地址 PING */
ip = acl_netdb_index_ip(dns_db, 0);
if (ip == NULL || *ip == 0) {
acl_msg_error("ip invalid");
acl_netdb_free(dns_db);
return;
}
/* 创建 ICMP 对象 */
chat = icmp_chat_create(NULL, 1);
/* 开始 PING */
if (strcmp(dest, ip) == 0)
icmp_ping_one(chat, NULL, ip, __npkt, delay, 1);
else
icmp_ping_one(chat, dest, ip, __npkt, delay, 1);
acl_netdb_free(dns_db); /* 释放域名解析对象 */
display_res(chat); /* 显示 PING 结果 */
icmp_chat_free(chat); /* 释放 ICMP 对象 */
if (--__nfibers == 0)
acl_fiber_stop();
}
static void usage(const char* progname)
{
printf("usage: %s [-h help] [-n npkt] [\"dest1 dest2 dest3...\"]\r\n",
progname);
printf("example: %s -n 10 www.sina.com.cn www.qq.com\r\n", progname);
}
/* 当收到 SIGINT 信号(即在 PING 过程中用户按下 ctrl + c)时的信号处理函数 */
static void on_sigint(int signo acl_unused)
{
exit(0);
}
int main(int argc, char* argv[])
{
char ch;
int i;
signal(SIGINT, on_sigint); /* 用户按下 ctr + c 时中断 PING 程序 */
acl_msg_stdout_enable(1); /* 允许 acl_msg_xxx 记录的信息输出至屏幕 */
while ((ch = getopt(argc, argv, "hn:")) > 0) {
switch (ch) {
case 'n':
__npkt = atoi(optarg);
break;
case 'h':
usage(argv[0]);
return 0;
default:
break;
}
}
if (optind == argc) {
usage(argv[0]);
return 0;
}
if (__npkt <= 0)
__npkt = 10;
/* 记录要启动的协程的总数 */
__nfibers = argc - optind;
for (i = optind; i < argc; i++)
acl_fiber_create(fiber_ping, argv[i], 32000);
acl_fiber_schedule();
return 0;
}

View File

@ -5,6 +5,7 @@
#include <unistd.h>
#include "fiber/lib_fiber.h"
static int __stack_size = 32000;
static int __rw_timeout = 0;
static int __echo_data = 0;
@ -57,7 +58,7 @@ static void fiber_accept(ACL_FIBER *fiber acl_unused, void *ctx)
}
printf("accept one, fd: %d\r\n", ACL_VSTREAM_SOCK(cstream));
acl_fiber_create(echo_client, cstream, 32768);
acl_fiber_create(echo_client, cstream, __stack_size);
}
acl_vstream_close(sstream);
@ -94,6 +95,7 @@ static void usage(const char *procname)
" -r rw_timeout\r\n"
" -S [if sleep]\r\n"
" -q listen_queue\r\n"
" -z stack_size\r\n"
" -w [if echo data, default: no]\r\n", procname);
}
@ -107,7 +109,7 @@ int main(int argc, char *argv[])
snprintf(addr, sizeof(addr), "%s", "127.0.0.1:9002");
while ((ch = getopt(argc, argv, "hs:r:Sq:w")) > 0) {
while ((ch = getopt(argc, argv, "hs:r:Sq:wz:")) > 0) {
switch (ch) {
case 'h':
usage(argv[0]);
@ -127,6 +129,9 @@ int main(int argc, char *argv[])
case 'w':
__echo_data = 1;
break;
case 'z':
__stack_size = atoi(optarg);
break;
default:
break;
}

View File

@ -1,3 +1,5 @@
1) 增加针对协程调度器的监控机制
2) 增加更方便的协程异步调用接口
3) 支持信号跳转方式
4) 支持 read 读缓冲