libevent

libevent
libevent

翻译:Libevent参考手册:前言

翻译自:https://www.360docs.net/doc/d94261441.html,/~nickm/libevent-book/Ref0_meta.html

1 从一万英尺外看Libevent

Libevent是用于编写高速可移植非阻塞IO应用的库,其设计目标是:

可移植性:使用libevent编写的程序应该可以在libevent支持的所有平台上工作。即使没有好的方式进行非阻塞IO,libevent也应该支持一般的方式,让程序可以在受限的环境中运行。

速度:libevent尝试使用每个平台上最高速的非阻塞IO实现,并且不引入太多的额外开销。

可扩展性:libevent被设计为程序即使需要上万个活动套接字的时候也可以良好工作。 方便:无论何时,最自然的使用libevent编写程序的方式应该是稳定的、可移植的。

libevent由下列组件构成:

evutil:用于抽象不同平台网络实现差异的通用功能。

event和event_base:libevent的核心,为各种平台特定的、基于事件的非阻塞IO后端提供抽象API,让程序可以知道套接字何时已经准备好,可以读或者写,并且处理基本的超时功能,检测OS信号。

bufferevent:为libevent基于事件的核心提供使用更方便的封装。除了通知程序套接字已经准备好读写之外,还让程序可以请求缓冲的读写操作,可以知道何时IO已经真正发生。(bufferevent接口有多个后端,可以采用系统能够提供的更快的非阻塞IO方式,如Windows中的IOCP。)

evbuffer:在bufferevent层之下实现了缓冲功能,并且提供了方便有效的访问函数。

evhttp:一个简单的HTTP客户端/服务器实现。

evdns:一个简单的DNS客户端/服务器实现。

evrpc:一个简单的RPC实现。

2 库

创建libevent时,默认安装下列库:

libevent_core:所有核心的事件和缓冲功能,包含了所有的event_base、evbuffer、bufferevent和工具函数。

libevent_extra:定义了程序可能需要,也可能不需要的协议特定功能,包括HTTP、DNS和RPC。

libevent:这个库因为历史原因而存在,它包含libevent_core和libevent_extra的内容。

不应该使用这个库,未来版本的libevent可能去掉这个库。

某些平台上可能安装下列库:

libevent_pthreads:添加基于pthread可移植线程库的线程和锁定实现。它独立于libevent_core,这样程序使用libevent时就不需要链接到pthread,除非是以多线程方式使用libevent。

libevent_openssl:这个库为使用bufferevent和OpenSSL进行加密的通信提供支持。它独立于libevent_core,这样程序使用libevent时就不需要链接到OpenSSL,除非是进行加密通信。

3 头文件

libevent公用头文件都安装在event2目录中,分为三类:

API头文件:定义libevent公用接口。这类头文件没有特定后缀。

兼容头文件:为已废弃的函数提供兼容的头部包含定义。不应该使用这类头文件,除非是在移植使用较老版本libevent的程序时。

结构头文件:这类头文件以相对不稳定的布局定义各种结构体。这些结构体中的一些是为了提供快速访问而暴露;一些是因为历史原因而暴露。直接依赖这类头文件中的任何结构体都会破坏程序对其他版本libevent的二进制兼容性,有时候是以非常难以调试的方式出现。这类头文件具有后缀“_struct.h”。

(还存在不在event2目录中的较老版本libevent的头文件,请参考下节:如果需要使用老版本libevent)

4 如果需要使用老版本libevent

libevent 2.0以更合理的、不易出错的方式修正了API。如果可能,编写新程序时应该使用libevent 2.0。但是有时候可能需要使用较老的API,例如在升级已存的应用时,或者支持因为某些原因不能安装2.0或者更新版本libevent的环境时。

较老版本的libevent头文件较少,也不安装在event2目录中。

在2.0以及以后版本的libevent中,老的头文件仍然会作为新头文件的封装而存在。

其他关于使用较老版本的提示:

1.4版之前只有一个库libevent,它包含现在分散到libevent_core和libevent_extra中的所

有功能。

2.0版之前不支持锁定:只有确定不同时在多个线程中使用同一个结构体时,libevent才

是线程安全的。

下面的节还将讨论特定代码区域可能遇到的已经废弃的API。

5 关于版本状态的提示

1.4.7及以前版本应该被认为是完全废弃的。1.3之前的版本应该被认为是充满bug的。(此外,不要向libevent维护者发送任何关于1.4.x或者更早版本的新特征,这些版本被认为是稳定的发布版本。如果在1.3x或者更早版本中发现bug,在报告之前请确定在最新的稳定发布版本中问题仍然存在:后续发布可能已经解决了问题。)

翻译:Libevent参考手册第一章:设置libevent

(2011-03-30 07:56:42)

转载

标签:

libevent

分类:读书笔记和翻译

网络编程

翻译自:https://www.360docs.net/doc/d94261441.html,/~nickm/libevent-book/Ref1_libsetup.html libevent有一些被整个进程共享的、影响整个库的全局设置。必须在调用libevent库的任何其他部分之前修改这些设置,否则,libevent会进入不一致的状态。

1 Libevent中的日志消息

libevent可以记录内部错误和警告。如果编译进日志支持,还会记录调试信息。默认配置下这些信息被写到stderr。通过提供定制的日志函数可以覆盖默认行为。

接口

#define _EVENT_LOG_DEBUG 0

#define _EVENT_LOG_MSG 1

#define _EVENT_LOG_WARN 2

#define _EVENT_LOG_ERR 3

typedef void (*event_log_cb)(int severity, const char *msg);

void event_set_log_callback(event_log_cb cb);

要覆盖libevent的日志行为,编写匹配event_log_cb签名的定制函数,将其作为参数传递给event_set_log_callback()。随后libevent在日志信息的时候,将会把信息传递给你提供的函数。再次调用event_set_log_callback(),传递参数NULL,就可以恢复默认行为。示例

#include

#include

static void discard_cb(int severity, const char *msg)

{

/* This callback does nothing. */

}

static FILE *logfile = NULL;

static void write_to_file_cb(int severity, const char *msg)

{

const char *s;

if (!logfile)

return;

switch (severity) {

case _EVENT_LOG_DEBUG: s = "debug"; break;

case _EVENT_LOG_MSG: s = "msg"; break;

case _EVENT_LOG_WARN: s = "warn"; break;

case _EVENT_LOG_ERR: s = "error"; break;

default: s = "?"; break; /* never reached */

}

fprintf(logfile, "[%s] %s\n", s, msg);

}

/* Turn off all logging from Libevent. */

void suppress_logging(void)

{

event_set_log_callback(discard_cb);

}

/* Redirect all Libevent log messages to the C stdio file 'f'. */

void set_logfile(FILE *f)

{

logfile = f;

event_set_log_callback(write_to_file_cb);

}

注意

在用户提供的event_log_cb回调函数中调用libevent函数是不安全的。比如说,如果试图编写一个使用bufferevent将警告信息发送给某个套接字的日志回调函数,可能会遇到奇怪而难以诊断的bug。未来版本libevent的某些函数可能会移除这个限制。

这个函数在中声明,在libevent 1.0c版本中首次出现。

2 处理致命错误

libevent在检测到不可恢复的内部错误时的默认行为是调用exit()或者abort(),退出正在运行的进程。这类错误通常意味着某处有bug:要么在你的代码中,要么在libevent 中。

如果希望更优雅地处理致命错误,可以为libevent提供在退出时应该调用的函数,覆盖默认行为。

接口

typedef void (*event_fatal_cb)(int err);

void event_set_fatal_callback(event_fatal_cb cb);

要使用这些函数,首先定义libevent在遇到致命错误时应该调用的函数,将其传递给event_set_fatal_callback()。随后libevent在遇到致命错误时将调用你提供的函数。

你的函数不应该将控制返回到libevent:这样做可能导致不确定的行为。为了避免崩溃,libevent还是会退出。你的函数被不应该调用其它libevent函数。

这些函数声明在中,在libevent 2.0.3-alpha版本中首次出现。

3 内存管理

默认情况下,libevent使用C库的内存管理函数在堆上分配内存。通过提供malloc、realloc 和free的替代函数,可以让libevent使用其他的内存管理器。希望libevent使用一个更高效的分配器时;或者希望libevent使用一个工具分配器,以便检查内存泄漏时,可能需要这样做。

接口

void event_set_mem_functions(void *(*malloc_fn)(size_t sz),

void *(*realloc_fn)(void *ptr, size_t sz), void (*free_fn)(void *ptr));

这里有个替换libevent分配器函数的示例,它可以计算已经分配的字节数。实际应用中可能需要添加锁,以避免运行在多个线程中时发生错误。

示例

#include

#include

#include

/* This union's purpose is to be as big as the largest of all the

* types it contains. */

union alignment {

size_t sz;

void *ptr;

double dbl;

};

/* We need to make sure that everything we return is on the right

alignment to hold anything, including a double. */

#define ALIGNMENT sizeof(union alignment)

/* We need to do this cast-to-char* trick on our pointers to adjust

them; doing arithmetic on a void* is not standard. */

#define OUTPTR(ptr) (((char*)ptr)+ALIGNMENT)

#define INPTR(ptr) (((char*)ptr)-ALIGNMENT)

static size_t total_allocated = 0;

static void *replacement_malloc(size_t sz)

{

void *chunk = malloc(sz + ALIGNMENT);

if (!chunk) return chunk;

total_allocated += sz;

*(size_t*)chunk = sz;

return OUTPTR(chunk);

}

static void *replacement_realloc(void *ptr, size_t sz)

{

size_t old_size = 0;

if (ptr) {

ptr = INPTR(ptr);

old_size = *(size_t*)ptr;

}

ptr = realloc(ptr, sz + ALIGNMENT);

if (!ptr)

return NULL;

*(size_t*)ptr = sz;

total_allocated = total_allocated - old_size + sz;

return OUTPTR(ptr);

}

static void replacement_free(void *ptr)

{

ptr = INPTR(ptr);

total_allocated -= *(size_t*)ptr;

free(ptr);

}

void start_counting_bytes(void)

{

event_set_mem_functions(replacement_malloc,

replacement_realloc,

replacement_free);

}

注意

替换内存管理函数影响libevent随后的所有分配、调整大小和释放内存操作。所以,必须保证在调用任何其他libevent函数之前进行替换。否则,libevent可能用你的free函数释放用C库的malloc分配的内存。

你的malloc和realloc函数返回的内存块应该具有和C库返回的内存块一样的地址对齐。 你的realloc函数应该正确处理realloc(NULL,sz)(也就是当作malloc(sz)处理)

你的realloc函数应该正确处理realloc(ptr,0)(也就是当作free(ptr)处理)

你的free函数不必处理free(NULL)

你的malloc函数不必处理malloc(0)

如果在多个线程中使用libevent,替代的内存管理函数需要是线程安全的。

libevent将使用这些函数分配返回给你的内存。所以,如果要释放由libevent函数分配和返回的内存,而你已经替换malloc和realloc函数,那么应该使用替代的free函数。

event_set_mem_functions函数声明在中,在libevent 2.0.1-alpha版本中首次出现。

可以在禁止event_set_mem_functions函数的配置下编译libevent。这时候使用event_set_mem_functions将不会编译或者链接。在2.0.2-alpha及以后版本中,可以通过检查是否定义了EVENT_SET_MEM_FUNCTIONS_IMPLEMENTED宏来确定event_set_mem_functions函数是否存在。

4 锁和线程

编写多线程程序的时候,在多个线程中同时访问同样的数据并不总是安全的。

libevent的结构体在多线程下通常有三种工作方式:

某些结构体内在地是单线程的:同时在多个线程中使用它们总是不安全的。

某些结构体具有可选的锁:可以告知libevent是否需要在多个线程中使用每个对象。

某些结构体总是锁定的:如果libevent在支持锁的配置下运行,在多个线程中使用它们总是安全的。

为获取锁,在调用分配需要在多个线程间共享的结构体的libevent函数之前,必须告知libevent使用哪个锁函数。

如果使用pthreads库,或者使用Windows本地线程代码,那么你是幸运的:已经有设置libevent使用正确的pthreads或者Windows函数的预定义函数。

接口

#ifdef WIN32

int evthread_use_windows_threads(void);

#define EVTHREAD_USE_WINDOWS_THREADS_IMPLEMENTED

#endif

#ifdef _EVENT_HAVE_PTHREADS

int evthread_use_pthreads(void);

#define EVTHREAD_USE_PTHREADS_IMPLEMENTED

#endif

这些函数在成功时都返回0,失败时返回-1。

如果使用不同的线程库,则需要一些额外的工作,必须使用你的线程库来定义函数去实现:

锁定

解锁

分配锁

析构锁

条件变量

创建条件变量

析构条件变量

等待条件变量

触发/广播某条件变量

线程

线程ID检测

使用evthread_set_lock_callbacks和evthread_set_id_callback接口告知libevent这些函数。接口

#define EVTHREAD_WRITE 0x04

#define EVTHREAD_READ 0x08

#define EVTHREAD_TRY 0x10

#define EVTHREAD_LOCKTYPE_RECURSIVE 1

#define EVTHREAD_LOCKTYPE_READWRITE 2

#define EVTHREAD_LOCK_API_VERSION 1

struct evthread_lock_callbacks {

int lock_api_version;

unsigned supported_locktypes;

void *(*alloc)(unsigned locktype);

void (*free)(void *lock, unsigned locktype);

int (*lock)(unsigned mode, void *lock);

int (*unlock)(unsigned mode, void *lock);

};

int evthread_set_lock_callbacks(const struct evthread_lock_callbacks *);

void evthread_set_id_callback(unsigned long (*id_fn)(void));

struct evthread_condition_callbacks {

int condition_api_version;

void *(*alloc_condition)(unsigned condtype);

void (*free_condition)(void *cond);

int (*signal_condition)(void *cond, int broadcast);

int (*wait_condition)(void *cond, void *lock,

const struct timeval *timeout);

};

int evthread_set_condition_callbacks(

const struct evthread_condition_callbacks *);

evthread_lock_callbacks结构体描述的锁回调函数及其能力。对于上述版本,lock_api_version字段必须设置为EVTHREAD_LOCK_API_VERSION。必须设置supported_locktypes字段为EVTHREAD_LOCKTYPE_*常量的组合以描述支持的锁类型(在2.0.4-alpha版本中,EVTHREAD_LOCK_RECURSIVE是必须的,EVTHREAD_LOCK_READWRITE则没有使用)。alloc函数必须返回指定类型的新锁;free 函数必须释放指定类型锁持有的所有资源;lock函数必须试图以指定模式请求锁定,如果成功则返回0,失败则返回非零;unlock函数必须试图解锁,成功则返回0,否则返回非零。可识别的锁类型有:

0:通常的,不必递归的锁。

EVTHREAD_LOCKTYPE_RECURSIVE:不会阻塞已经持有它的线程的锁。一旦持有它的线程进行原来锁定次数的解锁,其他线程立刻就可以请求它了。

EVTHREAD_LOCKTYPE_READWRITE:可以让多个线程同时因为读而持有它,但是任何时刻只有一个线程因为写而持有它。写操作排斥所有读操作。

可识别的锁模式有:

EVTHREAD_READ:仅用于读写锁:为读操作请求或者释放锁

EVTHREAD_WRITE:仅用于读写锁:为写操作请求或者释放锁

EVTHREAD_TRY:仅用于锁定:仅在可以立刻锁定的时候才请求锁定

id_fn参数必须是一个函数,它返回一个无符号长整数,标识调用此函数的线程。对于相同线程,这个函数应该总是返回同样的值;而对于同时调用该函数的不同线程,必须返回不同的值。

evthread_condition_callbacks结构体描述了与条件变量相关的回调函数。对于上述版本,condition_api_version字段必须设置为EVTHREAD_CONDITION_API_VERSION。alloc_condition函数必须返回到新条件变量的指针。它接受0作为其参数。free_condition函数必须释放条件变量持有的存储器和资源。wait_condition函数要求三个参数:一个由alloc_condition分配的条件变量,一个由你提供的evthread_lock_callbacks.alloc函数分配的锁,以及一个可选的超时值。调用本函数时,必须已经持有参数指定的锁;本函数应该释放指定的锁,等待条件变量成为授信状态,或者直到指定的超时时间已经流逝(可选)。wait_condition应该在错误时返回-1,条件变量授信时返回0,超时时返回1。返回之前,函数应该确定其再次持有锁。最后,signal_condition函数应该唤醒等待该条件变量的某个线程(broadcast参数为false时),或者唤醒等待条件变量的所有线程(broadcast参数为true时)。只有在持有与条件变量相关的锁的时候,才能够进行这些操作。

关于条件变量的更多信息,请查看pthreads的pthread_cond_*函数文档,或者Windows 的CONDITION_VARIABLE(Windows Vista新引入的)函数文档。

示例

关于使用这些函数的示例,请查看Libevent源代码发布版本中的evthread_pthread.c和evthread_win32.c文件。

这些函数在中声明,其中大多数在 2.0.4-alpha版本中首次出现。

2.0.1-alpha到2.0.3-alpha使用较老版本的锁函数。event_use_pthreads函数要求程序链接到event_pthreads库。

条件变量函数是2.0.7-rc版本新引入的,用于解决某些棘手的死锁问题。

可以创建禁止锁支持的libevent。这时候已创建的使用上述线程相关函数的程序将不能运行。

5 调试锁的使用

为帮助调试锁的使用,libevent有一个可选的“锁调试”特征。这个特征包装了锁调用,以便捕获典型的锁错误,包括:

解锁并没有持有的锁

重新锁定一个非递归锁

如果发生这些错误中的某一个,libevent将给出断言失败并且退出。

接口

void evthread_enable_lock_debuging(void);

注意

必须在创建或者使用任何锁之前调用这个函数。为安全起见,请在设置完线程函数后立即调用这个函数。

这个函数是在2.0.4-alpha版本新引入的。

6 调试事件的使用

libevent可以检测使用事件时的一些常见错误并且进行报告。这些错误包括:

将未初始化的event结构体当作已经初始化的

试图重新初始化未决的event结构体

跟踪哪些事件已经初始化需要使用额外的内存和处理器时间,所以只应该在真正调试程序的时候才启用调试模式。

接口

void event_enable_debug_mode(void);

必须在创建任何event_base之前调用这个函数。

如果在调试模式下使用大量由event_assign(而不是event_new)创建的事件,程序可能会耗尽内存,这是因为没有方式可以告知libevent由event_assign创建的事件不会再被使用了(可以调用event_free告知由event_new创建的事件已经无效了)。如果想在调试时避免耗尽内存,可以显式告知libevent这些事件不再被当作已分配的了:

接口

void event_debug_unassign(struct event *ev);

没有启用调试的时候调用event_debug_unassign没有效果。

这些调试函数在libevent 2.0.4-alpha版本中加入。

Example

#include

#include

#include

void cb(evutil_socket_t fd, short what, void *ptr)

{

/* We pass 'NULL' as the callback pointer for the heap allocated

* event, and we pass the event itself as the callback pointer

* for the stack-allocated event. */

struct event *ev = ptr;

if (ev)

event_debug_unassign(ev);

}

/* Here's a simple mainloop that waits until fd1 and fd2 are both

* ready to read. */

void mainloop(evutil_socket_t fd1, evutil_socket_t fd2, int debug_mode) {

struct event_base *base;

struct event event_on_stack, *event_on_heap;

if (debug_mode)

event_enable_debug_mode();

base = event_base_new();

event_on_heap = event_new(base, fd1, EV_READ, cb, NULL);

event_assign(&event_on_stack, base, fd2, EV_READ, cb, &event_on_stack);

event_add(event_on_heap, NULL);

event_add(&event_on_stack, NULL);

event_base_dispatch(base);

event_free(event_on_heap);

event_base_free(base);

}

7 检测libevent的版本

新版本的libevent会添加特征,移除bug。有时候需要检测libevent的版本,以便:

检测已安装的libevent版本是否可用于创建你的程序

为调试显示libevent的版本

检测libevent的版本,以便向用户警告bug,或者提示要做的工作

接口

#define LIBEVENT_VERSION_NUMBER 0x02000300

#define LIBEVENT_VERSION "2.0.3-alpha"

const char *event_get_version(void);

ev_uint32_t event_get_version_number(void);

宏返回编译时的libevent版本;函数返回运行时的libevent版本。注意:如果动态链接到libevent,这两个版本可能不同。

可以获取两种格式的libevent版本:用于显示给用户的字符串版本,或者用于数值比较的4字节整数版本。整数格式使用高字节表示主版本,低字节表示副版本,第三字节表示修正版本,最低字节表示发布状态:0表示发布,非零表示某特定发布版本的后续开发序列。

所以,libevent 2.0.1-alpha发布版本的版本号是[02 00 01 00],或者说0x02000100。

2.0.1-alpha和2.0.2-alpha之间的开发版本可能是[02 00 01 08],或者说0x02000108。

示例:编译时检测

#include

#if !defined(LIBEVENT_VERSION_NUMBER) || LIBEVENT_VERSION_NUMBER <

0x02000100

#error "This version of Libevent is not supported; Get 2.0.1-alpha or later."

#endif

int

make_sandwich(void)

{

/* Let's suppose that Libevent 6.0.5 introduces a make-me-a sandwich function. */

#if LIBEVENT_VERSION_NUMBER >= 0x06000500

evutil_make_me_a_sandwich();

return 0;

#else

return -1;

#endif

}

示例:运行时检测

#include

#include

int

check_for_old_version(void)

{

const char *v = event_get_version();

/* This is a dumb way to do it, but it is the only thing that works

before Libevent 2.0. */

if (!strncmp(v, "0.", 2) ||

!strncmp(v, "1.1", 3) ||

!strncmp(v, "1.2", 3) ||

!strncmp(v, "1.3", 3)) {

printf("Your version of Libevent is very old. If you run into bugs,"

" consider upgrading.\n");

return -1;

} else {

printf("Running with Libevent version %s\n", v);

return 0;

}

}

int

check_version_match(void)

{

ev_uint32_t v_compile, v_run;

v_compile = LIBEVENT_VERSION_NUMBER;

v_run = event_get_version_number();

if ((v_compile & 0xffff0000) != (v_run & 0xffff0000)) {

printf("Running with a Libevent version (%s) very different from the "

"one we were built with (%s).\n", event_get_version(),

LIBEVENT_VERSION);

return -1;

}

return 0;

}

本节描述的宏和函数定义在中。event_get_version函数首次出现在1.0c 版本;其他的首次出现在2.0.1-alpha版本。

翻译:libevent参考手册第二章:创建event_base

(2011-04-05 04:24:38)

转载

标签:

libevent

分类:读书笔记和翻译

网络编程

译自https://www.360docs.net/doc/d94261441.html,/~nickm/libevent-book/Ref2_eventbase.html

使用libevent函数之前需要分配一个或者多个event_base结构体。每个event_base 结构体持有一个事件集合,可以检测以确定哪个事件是激活的。

如果设置event_base使用锁,则可以安全地在多个线程中访问它。然而,其事件循环只能运行在一个线程中。如果需要用多个线程检测IO,则需要为每个线程使用一个event_base。

每个event_base都有一种用于检测哪种事件已经就绪的“方法”,或者说后端。可以识别的方法有:

select

poll

epoll

kqueue

devpoll

evport

win32

用户可以用环境变量禁止某些特定的后端。比如说,要禁止kqueue后端,可以设置EVENT_NOKQUEUE环境变量。如果要用编程的方法禁止后端,请看下面关于event_config_avoid_method()的说明。

1 建立默认的event_base

event_base_new()函数分配并且返回一个新的具有默认设置的event_base。函数会检测环境变量,返回一个到event_base的指针。如果发生错误,则返回NULL。选择各种方法时,函数会选择OS支持的最快方法。

接口

struct event_base *event_base_new(void);

大多数程序使用这个函数就够了。

event_base_new()函数声明在中,首次出现在libevent 1.4.3版。

2 创建复杂的event_base

要对取得什么类型的event_base 有更多的控制,就需要使用event_config。event_config是一个容纳event_base配置信息的不透明结构体。需要 event_base时,将event_config传递给event_base_new_with_config()。

2.1 接口

struct event_config *event_config_new(void);

struct event_base *event_base_new_with_config(const struct event_config *cfg);

void event_config_free(struct event_config *cfg);

要使用这些函数分配event_base,先调用event_config_new()分配一个event_config。然后,对event_config调用其它函数,设置所需要的event_base特征。最后,调用event_base_new_with_config()获取新的event_base。完成工作后,使用event_config_free()释放event_config。

2.2 接口

int event_config_avoid_method(struct event_config *cfg, const char

*method);

enum event_method_feature {

EV_FEATURE_ET = 0x01,

EV_FEATURE_O1 = 0x02,

EV_FEATURE_FDS = 0x04,

};

int event_config_require_features(struct event_config *cfg,

enum event_method_feature feature);

enum event_base_config_flag {

EVENT_BASE_FLAG_NOLOCK = 0x01,

EVENT_BASE_FLAG_IGNORE_ENV = 0x02,

EVENT_BASE_FLAG_STARTUP_IOCP = 0x04,

EVENT_BASE_FLAG_NO_CACHE_TIME = 0x08,

};

int event_config_set_flag(struct event_config *cfg,

enum event_base_config_flag flag);

调用 event_config_avoid_method()可以通过名字让libevent避免使用特定的可用后端。调用 event_config_require_feature()让libevent不使用不能提供所有指定特征的后端。调用 event_config_set_flag()让libevent在创建event_base时设置一个或者多个将在下面介绍的运行时标志。

event_config_require_features()可识别的特征值有:

EV_FEATURE_ET:要求支持边沿触发的后端

EV_FEATURE_O1:要求添加、删除单个事件,或者确定哪个事件激活的操作是O(1)复

杂度的后端

EV_FEATURE_FDS:要求支持任意文件描述符,而不仅仅是套接字的后端

event_config_set_flag()可识别的选项值有:

EVENT_BASE_FLAG_NOLOCK:不要为event_base分配锁。设置这个选项可以为event_base 节省一点用于锁定和解锁的时间,但是让在多个线程中访问event_base成为不安全的。 EVENT_BASE_FLAG_IGNORE_ENV:选择使用的后端时,不要检测EVENT_*环境变量。使用这个标志需要三思:这会让用户更难调试你的程序与libevent的交互。

EVENT_BASE_FLAG_STARTUP_IOCP:仅用于Windows,让libevent在启动时就启用任何必需的IOCP分发逻辑,而不是按需启用。

EVENT_BASE_FLAG_NO_CACHE_TIME:不是在事件循环每次准备执行超时回调时检测当前时间,而是在每次超时回调后进行检测。注意:这会消耗更多的CPU时间。

EVENT_BASE_FLAG_EPOLL_USE_CHANGELIST:告诉libevent,如果决定使用epoll后端,可以安全地使用更快的基于changelist的后端。epoll-changelist后端可以在后端的分发函数调用之间,同样的fd多次修改其状态的情况下,避免不必要的系统调用。

但是如果传递任何使用dup()或者其变体克隆的fd给 libevent,epoll-changelist 后端会触发一个内核bug,导致不正确的结果。在不使用epoll后端的情况下,这个标志是没有效果的。也可以通过设置EVENT_EPOLL_USE_CHANGELIST环境变量来打开epoll-changelist选项。

上述操作event_config的函数都在成功时返回0,失败时返回-1。

注意

设置event_config,请求OS 不能提供的后端是很容易的。比如说,对于libevent 2.0.1-alpha,在Windows中是没有O(1)后端的;在Linux中也没有同时提供EV_FEATURE_FDS 和EV_FEATURE_O1特征的后端。如果创建了libevent不能满足的配置,event_base_new_with_config()会返回 NULL。

2.3 接口

int event_config_set_num_cpus_hint(struct event_config *cfg, int cpus)

这个函数当前仅在Windows上使用 IOCP时有用,虽然将来可能在其他平台上有用。这个函数告诉event_config在生成多线程event_base的时候,应该试图使用给定数目的 CPU。注意这仅仅是一个提示:event_base使用的CPU可能比你选择的要少。

示例

struct event_config *cfg;

struct event_base *base;

int i;

/* My program wants to use edge-triggered events if at all possible. So

I'll try to get a base twice: Once insisting on edge-triggered IO, and

once not. */

for (i=0; i<2; ++i) {

cfg = event_config_new();

/* I don't like select. */

event_config_avoid_method(cfg, "select");

if (i == 0)

event_config_require_features(cfg, EV_FEATURE_ET);

base = event_base_new_with_config(cfg);

event_config_free(cfg);

if (base)

break;

/* If we get here, event_base_new_with_config() returned NULL. If

this is the first time around the loop, we'll try again without setting EV_FEATURE_ET. If this is the second time around the loop, we'll give up. */

社会调查研究方法笔记整理

第二部分社会调查研究方法 要求考生了解社会调查研究的科学过程,了解具体的调查设计与实施方法,了解资料分析的方法及撰写调查报告的要求。 一、社会调查研究的主要过程与内容 社会科学领域常见的研究方式:实验研究、调查研究(社会调查)、实地研究和文献研究。社会调查概念:指的是一种采用自填式问卷或结构式访问的方法,通过直接的询问,从一个取自总体的样本那里收集系统的、量化的资料,并通过对这些资料的统计分 析来认识社会现象及其规律的社会研究方式。 社会调查基本要素:抽样、问卷、统计分析。 社会调查的特征:首先,社会调查在本质上是一种定量的研究方式。其次,社会调查是一种 横剖性的社会研究方式。 社会调查的类型:调查对象范围——普遍调查与抽样调查;收集资料方法——问卷调查(自填问卷与邮寄问卷)和访问调查(当面访问与电话访问);调查目的或作 用——描述性调查和解释性调查;调查性质和应用领域——行政统计调 查、生活状况调查、社会问题调查、市场调查、民意调查和研究性调查。 社会调查的题材:某一人群的社会背景、某一人群的社会行为和活动、某一人群的意见和态度。 普遍调查和抽样调查:抽样调查指从所研究的总体中,按照一定的方式选取一部分个体进行调查,并将在这部分个体中所得到的调查结果推广到总体中去。优点:抽 样调查非常节省时间、人力和财力;十分迅速的获得资料数据;可以比较 详细的收集信息,获得内容丰富的资料;应用范围十分广泛;准确性高。 传统社会调查和现代社会调查: 1、社会调查研究的主要过程与内容:o(╯□╰)o 2、调查研究的主要阶段 a) 确定研究课题并将其系统化(选题阶段) b) 设计研究方案和准备研究工具(准备阶段) c) 资料的收集(实施阶段) d) 资料的处理与分析(分析阶段) e) 结果的解释与报告(总结阶段) 选题阶段的任务:一是选取主题,二是形成研究问题。选择问题阶段受多种因素制约:主观:研究者理论素养、生活阅历、观察角度、研究兴趣;客观:社会环境 等。研究问题选择好坏在一定程度上决定了这个研究工作的成败。 研究设计阶段由两部分组成:道路选择(为了达到研究的目标而进行的研究设计工作,设计研究的思路、策略、方式、方法以及具体技术工具等各个方面);工具准备(对 研究所依赖的测量工具或信息收集工具如问卷、量表、实验手段等等的准备。 问卷的准备和调查对象的选取工作)。 资料收集阶段:主要任务是具体贯彻研究设计中所确定的思路和策略,按照研究设计中所确定的方式、方法和技术进行资料的收集工作。 资料分析阶段:对收集的原始资料进行系统的审核、整理、归类、统计和分析。 得出结果阶段:撰写研究报告,评价研究质量,交流研究成果。

「ROS与C 入门教程」搭建开发环境(QT ros_qtc_plugin)

「ROS与C 入门教程」搭建开发环境(QT ros_qtc_plugin) 说明:介绍如何搭建QT环境来开发ROS包介绍QT 安装介绍QT编译和调试ROS包测试环境:系统版本:Ubuntu14.04ROS版本:indigoQT版本:5.8.0QtCreator 安装安装前准备,安装相应的GNU开发工具集和OpenGL 开发库,请注意安装软件都需要root权限,并且要联网安装sudo apt-get install build-essential libgl1-mesa-dev libevent-pthreads-2.0.5 doxygen xorg-dev下载64位Linux 安装包为qt-opensource-linux-x64-5.8.0.run。下载地址:http://download.qt.io/archive/qt/5.8/5.8.0/qt-opensource-lin ux-x64-5.8.0.run下载的run文件不一定具有可执行权限,可以执行如下命令开启执行权限(以64位安装包为例)cd ~/tools/wget http://download.qt.io/archive/qt/5.8/5.8.0/qt-opensource-lin ux-x64-5.8.0.runchmod +x ~/tools/qt-opensource-linux-x64-5.8.0.run桌面下,点击文件,进入tools,双击 .run 安装文件直接图形界面安装注册帐号,需要邮箱和密码。可以先进入网站注册帐号,https://login.qt.io/register.默认安装在/home//Qt5.8.0下需要的Qt组件和工具,默认不安装源码默认Next完整安装,完成后点左上角的Dash home,输入“qt”如果看到Qt

(完整word版)行测总结笔记 学霸笔记 必过

现在开始 资料分析 之所以把资料分析放在第一,是因为本人以前最怕资料分析不难但由于位于最后,时间紧加上数字繁琐,得分率一直很低。而各大论坛上的普遍说法是资料分析分值较高,不可小觑。有一次去面试,有个行测考90分的牛人说他拿到试卷先做资料分析,我也试过,发觉效果并不好,细想来经验因人而议,私以为资料分析还是应该放在最后,只是需要保证平均5分钟一篇的时间余量,胆大心细。 一、基本概念和公式 1、同比增长速度(即同比增长率)=(本期数-去年同期数)/去年同期数x100% =本期数/去年同期数-1 显然后一种快得多 环比增长速度(即环比增长率)=(本期数-上期数)/上期数=本期数/上期数-1 2、百分数、百分比(略) 3、比重(略) 4、倍数和翻番 翻番是指数量的加倍,翻番的数量以2^n次变化 5、平均数(略) 6、年均增长率 如果第一年的数据为A,第n+1年为B 二、下面重点讲一下资料分析速算技巧 1、a=b÷(1+x%)≈b×(1-x%)结果会比正确答案略小,记住是略小,如果看到有个选项比 你用这种方法算出来的结果略大,那么就可以选;比它小的结果不管多接近一律排除; x越小越精确 a=b÷(1-x%)≈bX(1+x%)结果会比正确答案略小,x越小越精确 特别注意: ⑴当选项差距比较大时,推荐使用该方法,当差距比较小时,需验证 ⑵增长率或者负增长率大于10%,不适用此方法 2、分子分母比较法 ⑴分子大分母小的分数大于分子小分母大的分数 ⑵差分法★ 若其中一个分数的分子和分母都大于另外一个分数的分子和分母,且大一点点时,差分法非常适用。 例:2008年产猪6584头,2009年产猪8613头,2010年产猪10624头,问2009与2010哪一年的增长率高 答:2009增长率8613/6584-1 ,2010增长率10624/8613-1,-1不用看,利用差分法

memcacheQ 配置

memcacheQ 配置 什么是memcacheQ ? memcacheQ是一个基于memcache协议、BDB持久数据存储、高性能轻量级队列服务程序。 特点是: 1.简单高效,基于memcache协议,这意味着只要客户端支持memcache协议即可使用。 2.队列数据存储于BDB,持久保存。 3.并发性能好。 4.支持多条队列。 并发量较的web环境,特别是数据库写入操作过多的情景,使用队列可大大缓解因并发问题造成的数据库锁死问题。生产环境中使用效果非常好。 先决条件: memcacheQ依赖于libevent,libevent-devel和BDB (BerkleyDB) 1.先检查libevent, libevent-devel是否已经安装: rpm -qa|grep libevent 输出中必须包含libevent, libevent-deve, 如果缺失,使用以下命令安装: yum install libevent yum install libevent-devel 安装完毕再复查之:rpm -qa|grep libevent, 确保安装正确。 注意事项:libevent, libevent-devel优先使用yum安装源,光盘镜像中的rpm包安装,这样稳定性和兼容性可得到保证,网上流传的使用源码安装libevent的方法会有问题,因为很可能系统已经安装libevent, 再使用源码安装,必然导致冲突,造成意外问题,所以一定要使用上述命令检查系统是否已经安装相应的库。 2.安装BerkleyDB cd /usr/local/src wget http://219.239.89.57/deploy/db-5.2.28.tar.gz tar zxvf db-5.2.28.tar.gz cd db-5.2.28 cd build_unix ../dist/configure make make install 3.准备安装memcacheQ cd /usr/local/src wget http://219.239.89.57/deploy/memcacheq-0.2.0.tar.gz tar zxvf memcacheq-0.2.0.tar.gz cd memcacheq-0.2.0 修改configure文件,找到bdbdir="/usr/local/BerkeleyDB.4.7",修改为 bdbdir="/usr/local/BerkeleyDB.5.2", 否则执行configure时会产生找不到BDB的错误。

linux服务器部署方案

服务器部署方案 应用架构 3台服务器,操作系统要求red hat linux enterprise 4 内核版本2.6.9-67. 注:在安装的时候要安装防火墙 基础软件要求: 1. Java环境: jdk-6u13-linux-i586-rpm.bin 2. Tomcat 环境: apache-tomcat-7.0.6.tar.gz 3.MYSQlDB 环境: MySQL-server-5.1.57-1.glibc23.i386.rpm,MySQL-client-5.1.57-1.glibc23.i386.rpm 4. memcached缓存环境: libevent-1.3.tar.gz ,memcached-1.2.2.tar.gz

基础软件安装 Jdk安装: 安装步骤: 1. 新建temp文件夹在linux上比如根目录/temp 2.拷贝jdk-6u13-linux-i586-rpm.bin 到temp 下 3.chmod +x jdk-6u13-linux-i586.rpm.bin 4../jdk-6u13-linux-i586.rpm.bin 5.此时会生成文件jdk-6u13-linux-i58 6.rpm,同样给所有用户添加可执行的 权限 6.chmod +x jdk-6u13-linux-i586.rpm 7.安装程序 rpm -ivh jdk-6u13-linux-i586.rpm 8.出现安装协议等,按接受即可 设置步骤: 1.vi /etc/profile 在文件的最下面添加下面内容 JAVA_HOME=/usr/java/jdk1.6.0_13 CLASSPATH=.:$JAVA_HOME/lib/tools.jar:$JAVA_HOME/lib/dt.jar PATH=$JAVA_HOME/bin:/usr/bin:/usr/sbin:/bin:/sbin:/usr/X11R6/bin export JAVA_HOME CLASSPATH PATH 2.保存退出 3.检查 java -version 4.如果看到JVM版本及相关信息,即安装成功

lamp环境搭建_自己整理完整版

一、准备工作 在lamp环境中搭载网站 1.用winsp将网站目录copy到linux的php系统文件目录下/usr/local/apache2/htdocs 给runtime文件夹可写权限chmod 777 -R runtime 2.修改apache配置文件,修改网站首页 /usr/local/apache2/etc/http.conf 修改DirectoryIndex index.php index.html 重启apache:/usr/local/apache2/bin/apachectl restart 3.用小海豚(SQLyog) 文件/新建连接

将网页中的sql脚本导入到linux下的mysql数据库中启动mysql: 启动MySQL服务 1.用原本源代码的方式去使用和启动mysql /usr/local/mysql/bin/mysqld_safe --user=mysql & 2.重启以后还要生效: Vi /etc/rc.local /usr/local/mysql/bin/mysqld_safe --user=mysql & 进入mysql命令行 /usr/local/mysql/bin/mysql -u root -p550120

4.在windows下用浏览器访问192.168.1.1/网站目录 ============================================= 注意: 先创建/lamp文件夹 使用WinSCP 把要安装的压缩文件放到/lamp文件夹下 ./configure 执行的时候要注意不能有换行 Appche安装的时候一定要确认之前的安装已经卸载 http://192.168.255.1/index.html 这个地址要改成192.168.80.8 /usr/local/apache2/bin/apachectl start 有时候要用start有时候要用restart /usr/local/memcache/bin/memcached -umemcache & 中的-可能会有问题,要注意 1、安装编译工具gcc、gcc-c++、make 注意解决依赖关系,推荐使用yum安装,若不能联网可使用安装光盘做为yum源—— 1)编辑yum配置文件: Mount /dev/cdrom /media vi /etc/yum.repos.d/CentOS-Media.repo [c5-media] name=CentOS-$releasever - Media baseurl=file:///media * 修改为光盘挂载点 enabled=1 * 改为1意为启用 gpgcheck=0 gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-5 2)设置alias值: Vi /etc/bashrc alias yum="yum --disablerepo=\* --enablerepo=c5-media" 3)依次安装gcc、gcc-c++ Yum -y install gcc* 2、卸载系统Apache、MySQL和PHP的RPM安装包 下载前需关闭启动的服务,如httpd、mysqld service httpd stop service mysqld stop 卸载RPM包的Apache、MySQL、PHP yum remove httpd yum remove mysql 建议使用rpm –e http-1.2.3.rpm --nodeps (截断这个rpm包的依赖性) 3、关闭SELinux,允许防火墙80端口访问 1)关闭SELinux vi /etc/selinux/config SELINUX=disabled * 若安装时没有禁用SELinux ,将enforcing改为disabled 修改后需重新启动Linux方可生效! 2)关闭防火墙Netfilter/iptables 因尚未做防火墙讲解,直接简单的关闭所有防火墙设置: iptables -F * 如果没有禁用防火墙,默认80端口禁止访问 service iptables save 防火墙策略写到/etc/sysconfig/iptables,以后计算机重启再加载这个文件时,防火墙策略就会永久清空.

资料分析报告笔记整理好

资料分析笔记整理 一.资料分析基础概念与解题技巧 1.资料分析核心运算公式 2.资料分析常用基本概念 3.资料分析速算技巧 二.资料分析高频高点梳理 1.ABR类问题 2.比重类问题 资料分析基础概念与解题技巧 一、基期、本期 基期,表示的是在比较两个时期的变化时,用来做比较值(基准值)的时期,该时期的数值通常作为计算过程中的除数或者减数; 本期,相对于基期而言,是当前所处的时期,该时期的数值通常作为计算过程中的被除数或者被减数。 【注】和谁相比,谁做基期。 二、增长量、增长率(增长速度、增长幅度) 增长量,表示的是本期与基期之间的绝对差异,是一绝对值。 增长率,表示的是末期与基期之间的相对差异,是一相对值。 增长率=增长速度(增速)=增长幅度(增幅) 【注】在一些“最值”比较题的题干表述中,经常出现“增加(长)最多”和“增加(长)最快”,我们需要注意,前者比较的是增长量,而后者则比较的是增长率。 三、同比、环比 同比和环比均表示的是两个时期的变化情况,但是这两个概念比较的基期不同。同比,指的是本期发展水平与历史同期的发展水平的变化情况,其基期对应的是历史同期。 环比,指的是本期发展水平与上个统计周期的发展水平的变化情况,其基期对应的是上个统计周期。 【注】环比常出现在月份、季度相关问题。 四、公式运用与练习 资料分析的考察离不开对于两个时期的数值的比较,由此得出四个概念,

即基期(A),本期(B),增长率(R),增长量(X)。 增长量=基期量*增长率=本期量-基期量=本期量-本期量/1+增长率 增长率=增长量/基期量=(本期量-基期量)/基期量=本期量/基期量-1 本期=基期+增长量=基期+基期*增长率=基期*(1+增长率) 基期=本期-增长量=本期/1+增长率 【习题演练】 【例一】2012年1-3月,全国进出口总值为8593.7亿美元,同比增长7.3%,其中:出口4300.2亿美元,增长7.6%;进口4293.6亿美元,增长6.9%。3月当月,全国进出口总值为3259.7亿美元,同比增加216亿美元,其中:出口1656.6亿美元,增长135.4亿美元;进口1603.1亿美元,增长5.3%。 1、2011年一季度,全国进出口总值约为多少? 2、2012年一季度,全国出口额同比增长多少? 3、2011年三月份,全国进出口总值约为多少? 4、2012年三月份,全国出口总值同比增速约为多少? 【注】进出口相关问题,为资料分析中的一个易错点,注意题目中进出口、进口、出口的表述,注意进出口量与进出口额的不同,理解顺差、逆差的含义 出口-进口=顺差,反之则是逆差 2、资料分析常用基本概念 一、百分数、百分点 百分数,表示的是将相比较的基期的数值抽象为100,然后计算出来的数值,用“%”表示,一般通过数值相除得到,在资料分析题目常用在以下情况:(1)部分在整体中所占的比重;(2)表示某个指标的增长率或者减少率。 百分点,表示的是增长率、比例等以百分数表示的指标的变化情况,一般通过百分数相减得到,在资料分析题目常用在以下情况:(1)两个增长率、比例等以百分数表示的数值的差值;(2)在A拉动B增长几个百分点,这样的表述中。【例1】2010年,某省地区生产总值达到6835.7亿元,比去年同期增长14.9%。其中,第一产业增加值为483.5亿元,比去年同期增长25.8%,第二产业增加值为2985.6亿元,同比增长12.5%。 1、2010年,该省第一产业增加值占地区生产总值的比重为()。A.12.63% B.12.63个百分点 C.7.07% D.7.07个百分点 2、2010年,该省第一产业增加值同比增速比第二产业增加值增速高()。A.13.3% B.13.3个百分点 C.14.3% D.14.3个百分点 二、倍数、翻番 倍数,指将对比的基数抽象为1,从而计算出的数值。 翻番,指数量的加倍,如:如果某指标是原来的2倍,则意味着翻了一番,是原来的4倍,则意味着翻了两番,依此类推。所用的公式为:末期/基期=2n,即翻了n番。 【注】注意“超过N倍”“是xx的N倍”两种说法的区别。超过N倍,说明是基数的N+1倍。

服务器通信技术方案

服务器通信技术方案 前言1 1.服务器通讯需要解决的问题2 1.1单台RCU设备通讯情况2 1.2上万个RCU甚至达到将近百万终端与服务器同时通讯2 1.2.1 单台服务器2 1.2.2 集群服务器2 2.目前服务器通讯主流技术方案3 2.1 网上常用主流方案简介与比较3 2.1.1 传统的socket通讯模型3 2.1.2 Windows下IOCP模型3 2.1.3 linux下epoll模型4 2.1.4 其它的网络通讯第三方开源库简介及比较5 2.2服务器集群方案6 3.根据项目情况选择最合适方案8 3.1 推荐选择linux系统下的epoll及开源库Boost::asio8 3.2 可能问题8 RCU-U设备采集数据如:车辆诊断,通过GSM基站定位,内置GPS,GPRS系统提供远程数据,对车辆各个系统的运行状况(如ENG、ABS、ETC等)实时监测状态数据等。 这些数据的网络通讯平台,则由服务器提供的通讯技术来实现,因此如何实现这种多设备数据同时接收的技术方案很重要。本文将详细介绍相关技术及提出方案。

服务器通讯需要解决的问题 单台RCU设备通讯情况 主要通讯数据: 设备端,刚连接时登陆验证(设备端信息验证); 设备端,诊断数据及其它采集数据上传到服务器(估计频率每秒发一次); 服务器端,发送指令,实现对设备端的远程配置; RCU设备工程师估计的数据: 1每个RCU设备每秒钟产生一条数据,每条数据大概100个字节左右(0.1K左右); 从上数据显示如果达到: 100万级别的RCU用户量,需要服务器有近百兆的网络带宽吞吐量。 1000万级别的RCU用户量,需要服务器有近千兆的网络带宽吞吐量。 上万个RCU甚至达到将近百万终端与服务器同时通讯 1.2.1单台服务器 如果按照经典的server/client通讯模型,当有一个设备通过(TCP/UDP)连接服务器时,服务端单独开一个线程为这个设备数据服务,显然,当路数越多,我们的设备又是长连接方式,很快服务器将在设备近千路时服务器资源将达到上限,并且存在大量线程切换与管理问题。这时如果我们能合理利用单台服务器资源(如:windows 下iocp 模式,linux下的epoll网络通信模式等),在更优的管理模式下,将能接更多设备的服务(网上资料预估几千路的长连接甚至硬件较好配置下达到万路以上)。上面我们能在单台服务器在较好硬件配置和软件优化的模型管理下,能解决几千路上万路设备的长连接。 1.2.2集群服务器 但是,如果几十万台甚至接近百万级别的设备数量同时访问服务端时,这个时候需要涉及到一种合理的集群服务器架构模式。理论上,为了达到1:10000的连接,可以采用Server-Client 的连接方式,而为了达到1:10000*100的连接,我们怎么办呢?一般会采用Client-> ConnServer -> LogicServer。相当于有一批服务器来合理布局解决设备的大并发通讯问题。 ConnServer在接受完Client 的连接后,将Logic Server 暴露给Client,并立刻断开连接,称之为短连接。以后的数据交互就和Conn Server没有关系了,让Logic Server 直接跟client 再长连接通讯,这种架构有很多的优势。

公务员考试行测资料分析状元笔记

2017年公务员考试行测资料分析状元笔记通用阅读——上看标题,下看注释,中间看时间,单位(重点) 1文字性材料——难的是阅读(结构阅读是重点) 文字性材料阅读结构和中心 结构几段落——总分和并列—并列部分找中心词(圈点标点,括号标结构,圈标中心词)无结构小段,就仔细阅读,创造结构(圈点标点,标点暗示结构,括号标结构,圈标中心词)无结构大段,就直接读题—找两个关键词——区分性(平均气温),明显性(符号数字字母,例如括号,摄氏度,顿号之类的)——2007年底比2007年更合适 多个题目涉及同一个关键词的,可以一起做 2表格型材料——难的是计算 阅读横标目和纵标目 分清合计和项目和地区 3图形型材料——难的是理解 饼状图——看周围类别名称(包括大小的排名要心中有印象) 柱状趋势图——看横轴和纵轴(要注意两个纵轴的分别对应柱状和点) 柱状分两种:一种是绝对值(高低差异),一种是比例(高低相同,柱状分几个部分) 4统计术语(不是重点) 增长率是属于后一年(所以第一年的增长率是算不出来的) 前一年的总量=后一年除以(1+增长率)后一年除以(1-增长率) 增长率的对比(很容易会出隔两年的总量,倒推2次):增长率增长或降低了5个百分点(直接加减) 乘以2看成除以5 乘以5看成除以2 乘以25看成除以4 除以125看成乘以8 同比是与上一年的同一期相比较 环比是挨着的相同时间段相比较 同比和环比:如果有注释按注释为准 今年5月份环比=今年4月份 今年5月份同比=去年5月份 5统计性数据的要素——时间和单位(重点) 1时间表述(陷阱)——对时间很敏感 1.计算的年份不一样 2.计算的时间段不一样 2单位表述(陷阱)——对单位很敏感 1.饼状图有单位,就不是百分比 相比较的数据的单位不一样(注意是百分号还是千分号。年利率往往用百分,月利率用千分之) 2.计算的单位不一样 下列选项一定正确和一定错误的题目是最难的,可以放在最后做。

Libevent源码解析

libevent源码深度剖析 张亮 Email: sparling.liang@https://www.360docs.net/doc/d94261441.html,

回想刚开始写时,就冠以“深度剖析”的名称,也是为了给自己一些压力,以期能写好这一系列文章,对libevent源代码的各方面作详细的分析;现在看来也算是达到了最初的目的。希望能给学习和使用libevent的朋友们有所帮助。 Email:sparkling.liang@https://www.360docs.net/doc/d94261441.html, 张亮

目录 libevent源码深度剖析 (1) 目录 (3) 一序幕 (5) 1 前言 (5) 2 Libevent简介 (5) 3 学习的好处 (5) 二Reactor模式 (6) 1 Reactor的事件处理机制 (6) 2 Reactor模式的优点 (6) 3 Reactor模式框架 (6) 4 Reactor事件处理流程 (8) 5 小结 (9) 三基本使用场景和事件流程 (10) 1 前言 (10) 2 基本应用场景 (10) 3 实例代码 (11) 4 事件处理流程 (11) 5 小结 (12) 四libevent源代码文件组织 (13) 1 前言 (13) 2 源代码组织结构 (13) 3 小结 (14) 五libevent的核心:事件event (15) 1 libevent的核心-event (15) 2 libevent对event的管理 (16) 3 事件设置的接口函数 (17) 4 小结 (18) 六初见事件处理框架 (19) 1 事件处理框架-event_base (19) 2 创建和初始化event_base (20) 3 接口函数 (20) 4 小节 (23) 七事件主循环 (24) 1 阶段性的胜利 (24) 2 事件处理主循环 (24) 3 I/O和Timer事件的统一 (27) 4 I/O和Signal事件的统一 (27) 5 小节 (27) 八集成信号处理 (28) 1 集成策略——使用socket pair (28)

资料分析笔记整理样本

资料分析笔记整顿 一.资料分析基本概念与解题技巧 1.资料分析核心运算公式 2.资料分析惯用基本概念 3.资料分析速算技巧 二.资料分析高频高点梳理 1.ABR类问题 2.比重类问题 资料分析基本概念与解题技巧 一、基期、本期 基期,表达是在比较两个时期变化时,用来做比较值(基准值)时期,该时期数值普通作为计算过程中除数或者减数; 本期,相对于基期而言,是当前所处时期,该时期数值普通作为计算过程中被除数或者被减数。 【注】和谁相比,谁做基期。 二、增长量、增长率(增长速度、增长幅度) 增长量,表达是本期与基期之间绝对差别,是一绝对值。 增长率,表达是末期与基期之间相对差别,是一相对值。 增长率=增长速度(增速)=增长幅度(增幅) 【注】在某些“最值”比较题题干表述中,经常浮现“增长(长)最多”和“增长(长)最快”,咱们需要注意,前者比较是增长量,而后者则比较是增长率。 三、同比、环比 同比和环比均表达是两个时期变化状况,但是这两个概念比较基期不同。 同比,指是本期发展水平与历史同期发展水平变化状况,其基期相应是历史同期。

环比,指是本期发展水平与上个记录周期发展水平变化状况,其基期相应是上个记录周期。 【注】环比常出当前月份、季度有关问题。 四、公式运用与练习 资料分析考察离不开对于两个时期数值比较,由此得出四个概念, 即基期(A),本期(B),增长率(R),增长量(X)。 增长量=基期量*增长率=本期量-基期量=本期量-本期量/1+增长率 增长率=增长量/基期量=(本期量-基期量)/基期量=本期量/基期量-1 本期=基期+增长量=基期+基期*增长率=基期*(1+增长率) 基期=本期-增长量=本期/1+增长率 【习题演习】 【例一】1-3月,全国进出口总值为8593.7亿美元,同比增长7.3%,其中:出口4300.2亿美元,增长7.6%;进口4293.6亿美元,增长6.9%。3月当月,全国进出口总值为3259.7亿美元,同比增长216亿美元,其中:出口1656.6亿美元,增长135.4亿美元;进口1603.1亿美元,增长5.3%。 1、一季度,全国进出口总值约为多少? 2、一季度,全国出口额同比增长多少? 3、三月份,全国进出口总值约为多少? 4、三月份,全国出口总值同比增速约为多少? 【注】进出口有关问题,为资料分析中一种易错点,注意题目中进出口、进口、出口表述,注意进出口量与进出口额不同,理解顺差、逆差含义 出口-进口=顺差,反之则是逆差 2、资料分析惯用基本概念 一、百分数、百分点 百分数,表达是将相比较基期数值抽象为100,然后计算出来数值,用“%”表

粉笔资料分析听课笔记(整理版)

粉笔资料分析听课笔记(整理版)一、常用分数、百分数、平方 1 3=33.3% 1 4=25% 1 5=20% 1 6=16.7% 1 7=14.3% 1 8=12.5% 1 9=11.1% 1 10=10% 1 11=9.1% 1 12=8.3% 1 13=7.7% 1 14=7.1% 1 15=6.7% 1 16=6.3% 1 1.5=66.7% 1 2.25=44% 1 2.5=40% 1 3.5=28.6% 1 4.5=22% 1 5.5=18.2% 1 6.5=15.4% 1 7.5=13.3% 1 8.5=11.8% 1 9.5=10.5% 1 10.5=9.5% 1 11.5=8.7% 1 12.5=7.8% 1 13.5=7.4% 1 14.5=6.9% 1 15.5=6.5% 1 16.5=6.1% 22=2 32=942=1652=2562=3672=4982=64 92=81 102=100112= 121122=144132=169 142=196152=225 162=256 172=289182=324192=361202=400212=441 222=484232=529 242=576252 =625 262=676272=729 282=784292=841 二、截位直除速算法 三、其他速算技巧 1、一个数×1.5,等于这个数本身加上这个数的一半。 2、一个数×1.1等于这个数错位相加. 3、一个数×0.9等于这个数错位相减. 4、一个数÷5,等于这个数乘以2,乘积小数点向前移1位。

5、一个数÷25,等于这个数乘以4,乘积小数点向前移2位。 6、一个数÷125,等于这个数乘以8,乘积小数点向前移3位。 7、比较类:①分母相同,分子大的大;分子相同,分母小的大。 ②分子大分母小>分子小分母大。③当分母大分子大,分母小分子小时,看分母与分母的倍数,分子与分子的倍数,谁倍数大听谁的,谁小统统看为1,再比较。 四、统计术语 1、基期:相对于今年来说,去年的就是基期。 2、现期:相对于去年来说,今年的就是现期。 3、基期量:相对于今年来说,去年的量就是基期量。 4、现期量:相对于去年来说,今年的量就是基期量。 5、增长量:现期量和基期量的差值,就是增长量。 6、增长率:增长量与基期量的比值,就是增长率。 7、倍数:A 是B 的多少倍;A 为B 的多少倍,等于增长率加1。 辨析:A 比B 增长了500%,那么就是A 比B 增长(多)5倍,A 是B 的6倍。 8、比重:A 占B 的比重,A 占B 为多少;都等于 A B 。 A 占B 的比重比C 的比重为:A B - C B 。 9、平均数:在一组数据中所有数据之和再除以数据的个数。 10、同比:同比看年,今年与去年同期比。 11、环比:环比看尾,“年”“月”“日”等。

libevent 在linux下编译链接问题

libevent 在linux下编译链接问题 (2011-04-25 11:43:20) 转载▼ 分类:知识收集 标签: 杂谈 按照网上例子搞了个httpd的小demo(linvo_httpd.c),遇到一连串问题,努力google了半天,终于得解,记录之~ 环境: Linux 2.6.18-164.el5 libevent-1.4.13 首先用gcc编译时候报了类似下面信息的一堆错 /tmp/ccsKVcym.o: In function `main': linvo_httpd.c:(.text+0xdf): undefined reference to `event_init' linvo_httpd.c:(.text+0xf3): undefined reference to `evhttp_start' 应该是找不到编译后的libevent库文件所导致,可能是路径问题 这次在编译时加上了-levent参数后(让其到系统库中找event库),顺利编译通过 gcc -Wall linvo_httpd.c -o linvo_httpd -levent ./linvo_httpd 运行之~ 我擦,又来。。。。 ./linvo_httpd: error while loading shared libraries: libevent-1.4.so.2: cannot open shared object file: No such file or directory 依然是路径问题找不到文件 whereis libevent 看下我的libevent默认装到哪里了 libevent: /usr/local/lib/https://www.360docs.net/doc/d94261441.html, /usr/local/lib/libevent.so /usr/local/lib/libevent.a 哦~在/usr/local/lib/目录下 LD_DEBUG=libs ./linvo_httpd -v 看下demo程序究竟是到哪里去找的该文件 32372: find library=libevent-1.4.so.2 [0]; searching 32372: search cache=/etc/ld.so.cache 32372: search path=/lib/tls/i686/sse2:/lib/tls/i686:/lib/tls/sse2:/lib/tls:/lib/i686/sse2:/lib/i686:/lib/sse2:/lib:/usr/lib/ tls/i686/sse2:/usr/lib/tls/i686:/usr/lib/tls/sse2:/usr/lib/tls:/usr/lib/i686/sse2:/usr/lib/i686:/usr/lib/sse2 :/usr/lib (system search path) 32372: trying file=/lib/tls/i686/sse2/libevent-1.4.so.2 32372: trying file=/lib/tls/i686/libevent-1.4.so.2 32372: trying file=/lib/tls/sse2/libevent-1.4.so.2 32372: trying file=/lib/tls/libevent-1.4.so.2 32372: trying file=/lib/i686/sse2/libevent-1.4.so.2

黑马程序员C语言教程:libevent

标题:深入浅出-服务器高并发库libevent (一) 1安装 libevent是一个开源的高并发服务器开发包,官方地址https://www.360docs.net/doc/d94261441.html,/ libevent目前有两个版本一个是1.4系列版本,一个是2.0系列版本。 我们可以在官方网站上看到类似有个stable表示稳定版本。 libevent-1.4.15-stable.tar.gz 对于初学者学习,建议从1.4版本学起。 在安装libevent之前先判断本电脑是否已经安装了 通过指令 ls -al /usr/lib|grep libevent 如果没有任何信息则表示没有安装,有的话如果发现libevent是1.3以下版本,则可以同过执行rpm -e libevent —nodeps 进行卸载。如果是其他操作系统使用其他对应卸载指令即可。 对于下好的tar包,通过 tar -zxvf libevent-release-1.4.15-stable.tar.gz 指令解压。 然后执行./configure命令,但是有的包可能没有configure文件,却存在一个autogen.sh 脚本,运行这个脚本。 (如果运行不起来请安装autoconf包)

然后 ./configure–prefix=/usr make sudo make install 安装完之后执行 ls -al /usr/lib/|grep libevent 如果发现有libevent文件库存在就代表安装完毕。 2 简单的libevent服务器 我们通过连接libevent库来进行管理libevent库,所以在使用gcc或者g++编译的时候最后需要加上-levent 下面是一个简单的libevent服务器。 #include #include #include #include #include #include #include #include #include using namespace std;

粉笔资料分析听课笔记(整理版)

粉笔资料分析听课笔记(整理版) 一、常用分数、百分数、平方 13 =33.3% 14 =25% 15 =20% 16 =16.7% 17 =14.3% 1 8 =12.5% 19 =11.1% 110 =10% 111 =9.1% 112 =8.3% 113 =7.7% 1 14 =7.1% 115 =6.7% 1 16 =6.3% 11.5 =66.7% 12.25 =44% 12.5 =40% 13.5 =28.6% 14.5 =22% 15.5 =18.2% 16.5 =15.4% 17.5 =13.3% 18.5 =11.8% 19.5 =10.5% 110.5 =9.5% 111.5 =8.7% 112.5 =7.8% 113.5 =7.4% 114.5 =6.9% 115.5 =6.5% 116.5 =6.1% 22=2 32=9 42=16 52=25 62=36 72=49 82=64 92=81 102=100 112= 121 122=144 132=169 142=196 152=225 162=256 172=289 182=324 192=361 202=400 212=441 222=484 232=529 242=576 252 =625 262=676 272=729 282=784 292=841 二、截位直除速算法

三、其他速算技巧 1、一个数×1.5,等于这个数本身加上这个数的一半。 2、一个数×1.1等于这个数错位相加. 3、一个数×0.9等于这个数错位相减. 4、一个数÷5,等于这个数乘以2,乘积小数点向前移1位。 5、一个数÷25,等于这个数乘以4,乘积小数点向前移2位。 6、一个数÷125,等于这个数乘以8,乘积小数点向前移3位。 7、比较类:①分母相同,分子大的大;分子相同,分母小的大。 ②分子大分母小>分子小分母大。③当分母大分子大,分母小分子小时,看分母与分母的倍数,分子与分子的倍数,谁倍数大听谁的,谁小统统看为1,再比较。 四、统计术语 1、基期:相对于今年来说,去年的就是基期。 2、现期:相对于去年来说,今年的就是现期。 3、基期量:相对于今年来说,去年的量就是基期量。 4、现期量:相对于去年来说,今年的量就是基期量。 5、增长量:现期量和基期量的差值,就是增长量。 6、增长率:增长量与基期量的比值,就是增长率。 7、倍数:A是B的多少倍;A为B的多少倍,等于增长率加1。 辨析:A比B增长了500%,那么就是A比B增长(多)5倍,A是B的6倍。

黑马程序员C语言教程:深入浅出-服务器高并发库libevent

标题:深入浅出-服务器高并发库libevent (二) 上一章,我们简单介绍了libevent的环境的安装,和简单的事例。 现在先不要着急分析他的代码,在这里我首先要介绍一个专业名词“Reactor 模式”。 2.1 Reactor的事件处理机制 我们应该很清楚函数的调用机制。 1.程序调用函数 2.函数执行 3.程序等待函数将结果和控制权返回给程序 4.程序继续处理和执行 Reactor 被翻译成反应堆,或者反应器。Re-actor 发音。 他是一种事件驱动机制。和普通函数调用的不同之处在于,应用程序不是主动的调用某刻API完成处理,而是恰恰相反,reactor逆置了事件的处理流程,应用程序需要提供相应的接口注册到reacotr上。如果相应的事件发生。Reacotr将主动调用应用程序注册的接口,这些接口就是我们常常说的“回调函数”。 我们使用libevent框架也就是想利用这个框架去注册相应的事件和回调函数。当这些事件发生时,libevent会调用这些注册好的回调函数处理相应的事件(I/O 读写、定时和信号)

通过reactor调用函数,不是你主动去调用函数,而是等着系统调用。 一句话:“不用打电话给我们,我么会打电话通知你”。 举个例子,你去应聘某xx公司,面试结束后。 “普通函数调用机制”公司的HR比较懒,不会记你的联系方式,那咋办,你只能面试完自己打电话问结果。有没有被录取啊,还是被拒绝了。 “Reacotr”公司的HR就记下了你的联系方式,结果出来后HR会主动打电话通知你。有没有被录取啊,还是悲剧了。你不用自己打电话去问,实际上你也不能,你没有HR的联系方式。 2.2 Reactor模式的优点 Reactor模式是编写高性能网络服务器的必备技术之一,它具有如下的优点:1)响应快,不必为单个同步时间所阻塞,虽然Reactor本身依然是同步的; 2)编程相对简单,可以最大程度的避免复杂的多线程及同步问题,并且避免了多线程/进程的切换开销; 3)可扩展性,可以方便的通过增加Reactor实例个数来充分利用CPU资源;4)可复用性,reactor框架本身与具体事件处理逻辑无关,具有很高的复用性; 2.3 Reactor模式的必备条件 1)事件源 Linux上是文件描述符,Windows上就是Socket或者Handle了,这里统一称为“句柄集”;程序在指定的句柄上注册关心的事件,比如I/O事件。

相关文档
最新文档