日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Memcached 源码分析——从 main 函数说起

發布時間:2023/12/31 编程问答 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Memcached 源码分析——从 main 函数说起 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

(廣告時間: 最近在寫一個基于 Leveldb 存儲引擎的數據服務器,C開發,使用 Libevent 處理網絡事件,后臺利用多線程并發處理客戶端連接,理論上單機就應該支持數千-上萬的客戶端連接(未測試),框架已基本成型,暫取名LLDB(Libevent-based and Leveldb-backended DataBase),等代碼成熟以后將它開源,希望能有同學試用。)

Memcached? 是以 LiveJournal 旗下 Danga Interactive 公司的 Brad Fitzpatric? 為首開發的一款分布式緩存服務器,基于內存,性能非常高,現在已成為mixi、hatena、Facebook、Vox、LiveJournal等眾多服務中提高Web應用擴展性的重要因素(更多介紹參見:維基百科,百科百科)。下面粗略地分析一下 Memcached 的啟動流程(基于 memcached-1.4.14),此處只列出了代碼的梗概。

int main (int argc, char **argv) {int c;bool lock_memory = false;bool do_daemonize = false;bool preallocate = false;int maxcore = 0;char *username = NULL;char *pid_file = NULL;struct passwd *pw;struct rlimit rlim;char unit = '\0';int size_max = 0;int retval = EXIT_SUCCESS;/* listening sockets */static int *l_socket = NULL;/* 更多的參數設置 *//* 有效性檢查 */if (!sanitycheck()) {return EX_OSERR;}/* 注冊信號處理函數*/signal(SIGINT, sig_handler);/* 數據庫配置初始化 */settings_init();/* 處理輸入參數,并初始化 memcached 配置,代碼略 *//* 如果指定了 -S 參數,則初始化 sasl 模塊 */if (settings.sasl) {init_sasl();}/* 是否以守護進程方式運行 memcached*//* if we want to ensure our ability to dump core, don't chdir to / */if (do_daemonize) {if (sigignore(SIGHUP) == -1) {perror("Failed to ignore SIGHUP");}if (daemonize(maxcore, settings.verbose) == -1) {fprintf(stderr, "failed to daemon() in order to daemonize\n");exit(EXIT_FAILURE);}}/* 初始化 libevent 主線程實例 */main_base = event_init();/* 其他模塊初始化 */stats_init();assoc_init(settings.hashpower_init);conn_init();slabs_init(settings.maxbytes, settings.factor, preallocate);/** 忽視 SIGPIPE 信號,如果我們需要 SIGPIPE 信號,可以檢測條件 errno == EPIPE*/if (sigignore(SIGPIPE) == -1) {perror("failed to ignore SIGPIPE; sigaction");exit(EX_OSERR);}/* 如果以多線程模式運行 memcached,則啟動工作者線程 */thread_init(settings.num_threads, main_base);/* 啟動 assoc 維護線程*/if (start_assoc_maintenance_thread() == -1) {exit(EXIT_FAILURE);}/* 啟動 slab 維護線程 */if (settings.slab_reassign &&start_slab_maintenance_thread() == -1) {exit(EXIT_FAILURE);}/* 初始化時鐘處理函數 */clock_handler(0, 0, 0);/* 釋放特權后創建 unix 模式套接字 */if (settings.socketpath != NULL) {errno = 0;if (server_socket_unix(settings.socketpath,settings.access)) {vperror("failed to listen on UNIX socket: %s", settings.socketpath);exit(EX_OSERR);}}/* 創建監聽套接字,綁定該套接字,然后進行相關初始化 */if (settings.socketpath == NULL) {const char *portnumber_filename = getenv("MEMCACHED_PORT_FILENAME");char temp_portnumber_filename[PATH_MAX];FILE *portnumber_file = NULL;if (portnumber_filename != NULL) {snprintf(temp_portnumber_filename,sizeof(temp_portnumber_filename),"%s.lck", portnumber_filename);portnumber_file = fopen(temp_portnumber_filename, "a");if (portnumber_file == NULL) {fprintf(stderr, "Failed to open \"%s\": %s\n",temp_portnumber_filename, strerror(errno));}}errno = 0;if (settings.port && server_sockets(settings.port, tcp_transport,portnumber_file)) {vperror("failed to listen on TCP port %d", settings.port);exit(EX_OSERR);}/** 初始化順序:首先創建監聽套接字(低端口的套接字可能需要root權限),* 然后釋放 root 權限,如果設置以守護進程運行 memcached,則 Daemonise it。* 然后初始化 libevent 庫。*//* 創建 UDP 監聽套接字,并綁定該套接字 */errno = 0;if (settings.udpport && server_sockets(settings.udpport, udp_transport,portnumber_file)) {vperror("failed to listen on UDP port %d", settings.udpport);exit(EX_OSERR);}if (portnumber_file) {fclose(portnumber_file);rename(temp_portnumber_filename, portnumber_filename);}}if (pid_file != NULL) {save_pid(pid_file);}/* 釋放特權 */drop_privileges();/* 進入事件循環 */if (event_base_loop(main_base, 0) != 0) {retval = EXIT_FAILURE;}stop_assoc_maintenance_thread();/* 如果不是守護進程,則刪除 PID 文件 */if (do_daemonize)remove_pidfile(pid_file);/* Clean up strdup() call for bind() address */if (settings.inter)free(settings.inter);if (l_socket)free(l_socket);if (u_socket)free(u_socket);return retval; }

main 函數中值得注意的幾個函數調用如下:

  • conn_init();
  • thread_init(settings.num_threads, main_base);
  • clock_handler(0, 0, 0);
  • server_socket_unix(settings.socketpath,settings.access)
  • server_sockets(settings.port, tcp_transport, portnumber_file);
  • event_base_loop(main_base, 0);

在分析上面幾個函數之前我們來看看一些重要的變量和結構體的定義:

  • 重要變量聲明
static conn *listen_conn = NULL; static struct event_base *main_base;static conn **freeconns;
  • struct conn 結構體定義:
struct conn {int sfd;sasl_conn_t *sasl_conn;enum conn_states state;enum bin_substates substate;struct event event;short ev_flags;short which; /** which events were just triggered */char *rbuf; /** buffer to read commands into */char *rcurr; /** but if we parsed some already, this is where we stopped */int rsize; /** total allocated size of rbuf */int rbytes; /** how much data, starting from rcur, do we have unparsed */char *wbuf;char *wcurr;int wsize;int wbytes;/** which state to go into after finishing current write */enum conn_states write_and_go;void *write_and_free; /** free this memory after finishing writing */char *ritem; /** when we read in an item's value, it goes here */int rlbytes;/* data for the nread state *//*** item is used to hold an item structure created after reading the command* line of set/add/replace commands, but before we finished reading the actual* data. The data is read into ITEM_data(item) to avoid extra copying.*/void *item; /* for commands set/add/replace *//* data for the swallow state */int sbytes; /* how many bytes to swallow *//* data for the mwrite state */struct iovec *iov;int iovsize; /* number of elements allocated in iov[] */int iovused; /* number of elements used in iov[] */struct msghdr *msglist;int msgsize; /* number of elements allocated in msglist[] */int msgused; /* number of elements used in msglist[] */int msgcurr; /* element in msglist[] being transmitted now */int msgbytes; /* number of bytes in current msg */item **ilist; /* list of items to write out */int isize;item **icurr;int ileft;char **suffixlist;int suffixsize;char **suffixcurr;int suffixleft;enum protocol protocol; /* which protocol this connection speaks */enum network_transport transport; /* what transport is used by this connection *//* data for UDP clients */int request_id; /* Incoming UDP request ID, if this is a UDP "connection" */struct sockaddr request_addr; /* Who sent the most recent request */socklen_t request_addr_size;unsigned char *hdrbuf; /* udp packet headers */int hdrsize; /* number of headers' worth of space is allocated */bool noreply; /* True if the reply should not be sent. *//* current stats command */struct {char *buffer;size_t size;size_t offset;} stats;/* Binary protocol stuff *//* This is where the binary header goes */protocol_binary_request_header binary_header;uint64_t cas; /* the cas to return */short cmd; /* current command being processed */int opaque;int keylen;conn *next; /* Used for generating a list of conn structures */LIBEVENT_THREAD *thread; /* Pointer to the thread object serving this connection */ };
  • LIBEVENT_THREAD 和 LIBEVENT_DISPATCHER_THREAD定義:
typedef struct {pthread_t thread_id; /* unique ID of this thread */struct event_base *base; /* libevent handle this thread uses */struct event notify_event; /* listen event for notify pipe */int notify_receive_fd; /* receiving end of notify pipe */int notify_send_fd; /* sending end of notify pipe */struct thread_stats stats; /* Stats generated by this thread */struct conn_queue *new_conn_queue; /* queue of new connections to handle */cache_t *suffix_cache; /* suffix cache */ } LIBEVENT_THREAD;typedef struct {pthread_t thread_id; /* unique ID of this thread */struct event_base *base; /* libevent handle this thread uses */ } LIBEVENT_DISPATCHER_THREAD;

下面分析conn_init(); 函數:

static void conn_init(void) {freetotal = 200;freecurr = 0;if ((freeconns = calloc(freetotal, sizeof(conn *))) == NULL) {fprintf(stderr, "Failed to allocate connection structures\n");}return; }

基本上就是分配 freetotal 個 conn * 空間,非常簡單,

接下來是另外一個重要的函數調用:thread_init();

/** 初始化線程子模塊,創建各種 worker 線程。** nthreads 代表 worker 事件處理線程的數目* main_base 是主線程的event base。*/ void thread_init(int nthreads, struct event_base *main_base) {int i;int power;
/* 初始化鎖 */pthread_mutex_init(&cache_lock, NULL);pthread_mutex_init(&stats_lock, NULL);pthread_mutex_init(&init_lock, NULL);pthread_cond_init(&init_cond, NULL);pthread_mutex_init(&cqi_freelist_lock, NULL);cqi_freelist = NULL;/* Want a wide lock table, but don't waste memory */if (nthreads < 3) {power = 10;} else if (nthreads < 4) {power = 11;} else if (nthreads < 5) {power = 12;} else {/* 8192 buckets, and central locks don't scale much past 5 threads */power = 13;}item_lock_count = ((unsigned long int)1 << (power));item_lock_mask = item_lock_count - 1;item_locks = calloc(item_lock_count, sizeof(pthread_mutex_t));if (! item_locks) {perror("Can't allocate item locks");exit(1);}for (i = 0; i < item_lock_count; i++) {pthread_mutex_init(&item_locks[i], NULL);}threads = calloc(nthreads, sizeof(LIBEVENT_THREAD));if (! threads) {perror("Can't allocate thread descriptors");exit(1);}/* 設置 dispatcher_thread (即主線程)的相關結構 */dispatcher_thread.base = main_base;dispatcher_thread.thread_id = pthread_self();for (i = 0; i < nthreads; i++) {int fds[2];if (pipe(fds)) {perror("Can't create notify pipe");exit(1);}/* 此處用了一個 trick,worker 線程通過讀取 notify_receice_fd * 一個字節獲知主線程接受到了事件。 */threads[i].notify_receive_fd = fds[0];threads[i].notify_send_fd = fds[1];setup_thread(&threads[i]);/* 為 libevent 保留三個 fd,另外兩個預留給管道 */stats.reserved_fds += 5;}/* 完成了所有的 libevent 設置后創建 worker 線程 */for (i = 0; i < nthreads; i++) {create_worker(worker_libevent, &threads[i]);}/* 主線程等待所有的線程設置好了以后在返回 */pthread_mutex_lock(&init_lock);while (init_count < nthreads) {pthread_cond_wait(&init_cond, &init_lock);}pthread_mutex_unlock(&init_lock); } static LIBEVENT_DISPATCHER_THREAD dispatcher_thread;/** 每個 Libevent 實例都有一對喚醒的管道,其他線程可以想管道中寫入數據* 來告知他在隊列中放入了一個新的連接*/ static LIBEVENT_THREAD *threads;

thread_init() 中又調用了 setup_thread() 來設置每個 worker 線程的信息。

static void setup_thread(LIBEVENT_THREAD *me) {me->base = event_init();if (! me->base) {fprintf(stderr, "Can't allocate event base\n");exit(1);}/* Listen for notifications from other threads */event_set(&me->notify_event, me->notify_receive_fd,EV_READ | EV_PERSIST, thread_libevent_process, me);event_base_set(me->base, &me->notify_event);if (event_add(&me->notify_event, 0) == -1) {fprintf(stderr, "Can't monitor libevent notify pipe\n");exit(1);}me->new_conn_queue = malloc(sizeof(struct conn_queue));if (me->new_conn_queue == NULL) {perror("Failed to allocate memory for connection queue");exit(EXIT_FAILURE);}cq_init(me->new_conn_queue);if (pthread_mutex_init(&me->stats.mutex, NULL) != 0) {perror("Failed to initialize mutex");exit(EXIT_FAILURE);}me->suffix_cache = cache_create("suffix", SUFFIX_SIZE, sizeof(char*),NULL, NULL);if (me->suffix_cache == NULL) {fprintf(stderr, "Failed to create suffix cache\n");exit(EXIT_FAILURE);} }

并在setup_thread() 中設置 worker 線程的回調函數,thread_libevent_process() :

/** 當每個 worker 線程的喚醒管道(wakeup pipe)收到有連接到來的通知時,* 就調用該函數。*/ static void thread_libevent_process(int fd, short which, void *arg) {LIBEVENT_THREAD *me = arg;CQ_ITEM *item;char buf[1];if (read(fd, buf, 1) != 1)if (settings.verbose > 0)fprintf(stderr, "Can't read from libevent pipe\n");item = cq_pop(me->new_conn_queue);if (NULL != item) {conn *c = conn_new(item->sfd, item->init_state, item->event_flags,item->read_buffer_size, item->transport, me->base);if (c == NULL) {if (IS_UDP(item->transport)) {fprintf(stderr, "Can't listen for events on UDP socket\n");exit(1);} else {if (settings.verbose > 0) {fprintf(stderr, "Can't listen for events on fd %d\n",item->sfd);}close(item->sfd);}} else {c->thread = me;}cqi_free(item);} }

thread_init() 中還調用了create_worker() 函數創建 worker 線程,同時設置worker 線程的回調函數為 worker_libevent():

/** Worker 線程: 事件循環*/ static void *worker_libevent(void *arg) {LIBEVENT_THREAD *me = arg;/* thread_init() 會一直阻塞到所有的線程完成初始化*/pthread_mutex_lock(&init_lock);init_count++;pthread_cond_signal(&init_cond);pthread_mutex_unlock(&init_lock);/* worker 線程進入事件循環 */event_base_loop(me->base, 0);return NULL; }

至此 thread_init() 函數返回。

接下來一個比較重要的調用是server_sockets(),server_sockets() 中又調用了 server_socket(),然后在在 server_socket() 中又調用了 conn_new(),并在 conn_new()中設置事件的回調函數 event_handler(),

void event_handler(const int fd, const short which, void *arg) {conn *c;c = (conn *)arg;assert(c != NULL);c->which = which;/* sanity */if (fd != c->sfd) {if (settings.verbose > 0)fprintf(stderr, "Catastrophic: event fd doesn't match conn fd!\n");conn_close(c);return;}drive_machine(c);/* wait for next event */return; }

drive_machine() 函數可以說是一個大的狀態機,函數很長,

static void drive_machine(conn *c) {bool stop = false;int sfd, flags = 1;socklen_t addrlen;struct sockaddr_storage addr;int nreqs = settings.reqs_per_event;int res;const char *str;assert(c != NULL);while (!stop) {switch(c->state) {case conn_listening:addrlen = sizeof(addr);if ((sfd = accept(c->sfd, (struct sockaddr *)&addr, &addrlen)) == -1) {if (errno == EAGAIN || errno == EWOULDBLOCK) {/* these are transient, so don't log anything */stop = true;} else if (errno == EMFILE) {if (settings.verbose > 0)fprintf(stderr, "Too many open connections\n");accept_new_conns(false);stop = true;} else {perror("accept()");stop = true;}break;}if ((flags = fcntl(sfd, F_GETFL, 0)) < 0 ||fcntl(sfd, F_SETFL, flags | O_NONBLOCK) < 0) {perror("setting O_NONBLOCK");close(sfd);break;}if (settings.maxconns_fast &&stats.curr_conns + stats.reserved_fds >= settings.maxconns - 1) {str = "ERROR Too many open connections\r\n";res = write(sfd, str, strlen(str));close(sfd);STATS_LOCK();stats.rejected_conns++;STATS_UNLOCK();} else {dispatch_conn_new(sfd, conn_new_cmd, EV_READ | EV_PERSIST,DATA_BUFFER_SIZE, tcp_transport);}stop = true;break;case conn_waiting:if (!update_event(c, EV_READ | EV_PERSIST)) {if (settings.verbose > 0)fprintf(stderr, "Couldn't update event\n");conn_set_state(c, conn_closing);break;}conn_set_state(c, conn_read);stop = true;break;case conn_read:res = IS_UDP(c->transport) ? try_read_udp(c) : try_read_network(c);switch (res) {case READ_NO_DATA_RECEIVED:conn_set_state(c, conn_waiting);break;case READ_DATA_RECEIVED:conn_set_state(c, conn_parse_cmd);break;case READ_ERROR:conn_set_state(c, conn_closing);break;case READ_MEMORY_ERROR: /* Failed to allocate more memory *//* State already set by try_read_network */break;}break;case conn_parse_cmd :if (try_read_command(c) == 0) {/* wee need more data! */conn_set_state(c, conn_waiting);}break;case conn_new_cmd:/* Only process nreqs at a time to avoid starving otherconnections */--nreqs;if (nreqs >= 0) {reset_cmd_handler(c);} else {pthread_mutex_lock(&c->thread->stats.mutex);c->thread->stats.conn_yields++;pthread_mutex_unlock(&c->thread->stats.mutex);if (c->rbytes > 0) {/* We have already read in data into the input buffer,so libevent will most likely not signal read eventson the socket (unless more data is available. As ahack we should just put in a request to write data,because that should be possible ;-)*/if (!update_event(c, EV_WRITE | EV_PERSIST)) {if (settings.verbose > 0)fprintf(stderr, "Couldn't update event\n");conn_set_state(c, conn_closing);}}stop = true;}break;case conn_nread:if (c->rlbytes == 0) {complete_nread(c);break;}/* first check if we have leftovers in the conn_read buffer */if (c->rbytes > 0) {int tocopy = c->rbytes > c->rlbytes ? c->rlbytes : c->rbytes;if (c->ritem != c->rcurr) {memmove(c->ritem, c->rcurr, tocopy);}c->ritem += tocopy;c->rlbytes -= tocopy;c->rcurr += tocopy;c->rbytes -= tocopy;if (c->rlbytes == 0) {break;}}/* now try reading from the socket */res = read(c->sfd, c->ritem, c->rlbytes);if (res > 0) {pthread_mutex_lock(&c->thread->stats.mutex);c->thread->stats.bytes_read += res;pthread_mutex_unlock(&c->thread->stats.mutex);if (c->rcurr == c->ritem) {c->rcurr += res;}c->ritem += res;c->rlbytes -= res;break;}if (res == 0) { /* end of stream */conn_set_state(c, conn_closing);break;}if (res == -1 && (errno == EAGAIN || errno == EWOULDBLOCK)) {if (!update_event(c, EV_READ | EV_PERSIST)) {if (settings.verbose > 0)fprintf(stderr, "Couldn't update event\n");conn_set_state(c, conn_closing);break;}stop = true;break;}/* otherwise we have a real error, on which we close the connection */if (settings.verbose > 0) {fprintf(stderr, "Failed to read, and not due to blocking:\n""errno: %d %s \n""rcurr=%lx ritem=%lx rbuf=%lx rlbytes=%d rsize=%d\n",errno, strerror(errno),(long)c->rcurr, (long)c->ritem, (long)c->rbuf,(int)c->rlbytes, (int)c->rsize);}conn_set_state(c, conn_closing);break;case conn_swallow:/* we are reading sbytes and throwing them away */if (c->sbytes == 0) {conn_set_state(c, conn_new_cmd);break;}/* first check if we have leftovers in the conn_read buffer */if (c->rbytes > 0) {int tocopy = c->rbytes > c->sbytes ? c->sbytes : c->rbytes;c->sbytes -= tocopy;c->rcurr += tocopy;c->rbytes -= tocopy;break;}/* now try reading from the socket */res = read(c->sfd, c->rbuf, c->rsize > c->sbytes ? c->sbytes : c->rsize);if (res > 0) {pthread_mutex_lock(&c->thread->stats.mutex);c->thread->stats.bytes_read += res;pthread_mutex_unlock(&c->thread->stats.mutex);c->sbytes -= res;break;}if (res == 0) { /* end of stream */conn_set_state(c, conn_closing);break;}if (res == -1 && (errno == EAGAIN || errno == EWOULDBLOCK)) {if (!update_event(c, EV_READ | EV_PERSIST)) {if (settings.verbose > 0)fprintf(stderr, "Couldn't update event\n");conn_set_state(c, conn_closing);break;}stop = true;break;}/* otherwise we have a real error, on which we close the connection */if (settings.verbose > 0)fprintf(stderr, "Failed to read, and not due to blocking\n");conn_set_state(c, conn_closing);break;case conn_write:/** We want to write out a simple response. If we haven't already,* assemble it into a msgbuf list (this will be a single-entry* list for TCP or a two-entry list for UDP).*/if (c->iovused == 0 || (IS_UDP(c->transport) && c->iovused == 1)) {if (add_iov(c, c->wcurr, c->wbytes) != 0) {if (settings.verbose > 0)fprintf(stderr, "Couldn't build response\n");conn_set_state(c, conn_closing);break;}}/* fall through... */case conn_mwrite:if (IS_UDP(c->transport) && c->msgcurr == 0 && build_udp_headers(c) != 0) {if (settings.verbose > 0)fprintf(stderr, "Failed to build UDP headers\n");conn_set_state(c, conn_closing);break;}switch (transmit(c)) {case TRANSMIT_COMPLETE:if (c->state == conn_mwrite) {while (c->ileft > 0) {item *it = *(c->icurr);assert((it->it_flags & ITEM_SLABBED) == 0);item_remove(it);c->icurr++;c->ileft--;}while (c->suffixleft > 0) {char *suffix = *(c->suffixcurr);cache_free(c->thread->suffix_cache, suffix);c->suffixcurr++;c->suffixleft--;}/* XXX: I don't know why this wasn't the general case */if(c->protocol == binary_prot) {conn_set_state(c, c->write_and_go);} else {conn_set_state(c, conn_new_cmd);}} else if (c->state == conn_write) {if (c->write_and_free) {free(c->write_and_free);c->write_and_free = 0;}conn_set_state(c, c->write_and_go);} else {if (settings.verbose > 0)fprintf(stderr, "Unexpected state %d\n", c->state);conn_set_state(c, conn_closing);}break;case TRANSMIT_INCOMPLETE:case TRANSMIT_HARD_ERROR:break; /* Continue in state machine. */case TRANSMIT_SOFT_ERROR:stop = true;break;}break;case conn_closing:if (IS_UDP(c->transport))conn_cleanup(c);elseconn_close(c);stop = true;break;case conn_max_state:assert(false);break;}}return; }

可以說整個 memcached 就是圍繞這個狀態機運行的,可能的狀態如下:

enum conn_states {conn_listening, /**< 套接字監聽端口,等待新的連接 */conn_new_cmd, /**< 準備下一次命令的連接 */conn_waiting, /**< 等待可讀套接字 */conn_read, /**< 讀入命令行 */conn_parse_cmd, /**< 從輸入緩沖區中分析命令 */conn_write, /**< 響應寫出 */conn_nread, /**< 讀入固定大小的字節 */conn_swallow, /**< 去除不必要的存儲字節 */conn_closing, /**< 關閉連接 */conn_mwrite, /**< 順序寫 item */conn_max_state /**< 最大的狀態值,用于狀態Assertion(斷言) */ };

在 conn_listening 狀態時,接受新的客戶端連接,然后調用dispatch_new_connection():

/** 分發新的連接至其他線程,該函數只會在主線程中調用,* 調用時機為:主線程初始化(UDP模式)或者* 存在新的連接到來*/ void dispatch_conn_new(int sfd, enum conn_states init_state, int event_flags,int read_buffer_size, enum network_transport transport) {CQ_ITEM *item = cqi_new();int tid = (last_thread + 1) % settings.num_threads;LIBEVENT_THREAD *thread = threads + tid;last_thread = tid;item->sfd = sfd;item->init_state = init_state;item->event_flags = event_flags;item->read_buffer_size = read_buffer_size;item->transport = transport;cq_push(thread->new_conn_queue, item);MEMCACHED_CONN_DISPATCH(sfd, thread->thread_id);if (write(thread->notify_send_fd, "", 1) != 1) {perror("Writing to thread notify pipe");} }

至此,主線程和 worker 線程大部分邏輯均已介紹完畢,并各自進入自己的事件循環處理相應的業務。

讀后語:memcached 代碼簡介易讀,基于 Libevent 處理網絡事件,并采用了多線程機制,大大利用了多核的計算能力,提高了系統接受客戶端請求并發數量。

同時 memcached 在主線程和 worker 線程之間關于新連接到來的通知的處理也比較有趣,主線程和 worker 線程之間使用了一對管道來通信,每當主線程接受到新的連接時,它就向管道的一段寫入一個字節的數據,然后由于 worker 線程監聽了管道另外一端的事件,所以 worker 線程可以感知到新的連接到了,然后該連接被主線程 Dispatch 到某一個線程的隊列中,再由 worker 線程進行處理。

?

總結

以上是生活随笔為你收集整理的Memcached 源码分析——从 main 函数说起的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

国产一区二区在线免费播放 | 九九久久久久99精品 | 欧美精品免费在线观看 | 青青久草在线视频 | 日韩av一区二区三区在线观看 | 国产视频精品久久 | 99热在线免费观看 | 国产午夜精品一区 | 麻豆影视网 | 国产精品99页 | 天天操天天色天天 | 天天干天天操天天 | 9在线观看免费高清完整版 玖玖爱免费视频 | 97国产一区二区 | 欧美在线视频日韩 | 美女国内精品自产拍在线播放 | 久久人人添人人爽添人人88v | 九九热在线免费观看 | 美女视频黄的免费的 | 91av亚洲| av片在线观看免费 | 成年人免费av网站 | 久久在线 | 五月天色中色 | 久久午夜剧场 | 最近的中文字幕大全免费版 | 免费网站在线观看人 | 日韩在线视频一区二区三区 | 中文字幕av免费观看 | 免费亚洲视频在线观看 | 97免费在线视频 | 亚洲精品国偷拍自产在线观看蜜桃 | 欧美日韩在线免费视频 | 丁香六月天 | 91黄视频在线观看 | 国产日产精品一区二区三区四区 | 久久国产品 | 欧美激情h | 婷婷伊人五月 | 一区二区三区视频网站 | 玖玖在线看| 在线综合 亚洲 欧美在线视频 | 激情 婷婷 | 欧洲一区精品 | 8x成人在线| 在线成人av | 国产视频一区二区在线观看 | 久久五月婷婷丁香 | 成人亚洲网| 成人黄色大片网站 | 摸bbb搡bbb搡bbbb| 亚洲国产精品电影 | 婷婷丁香导航 | 国产涩涩在线观看 | 国产一级片一区二区三区 | 欧美成人一区二区 | 日本在线观看视频一区 | 91精品一区国产高清在线gif | 国产自在线观看 | www99精品 | 99精品在线观看 | 一本一本久久a久久精品综合妖精 | 在线播放日韩av | 亚洲一区视频在线播放 | 亚洲精品久久激情国产片 | 久久国产亚洲精品 | av三级av | 国产视频二区三区 | 中文字幕黄色av | 精品久久在线 | 2021国产视频 | 99精品亚洲 | 亚洲综合激情 | 精品国产一区二区三区在线观看 | 97av影院 | 国产免费三级在线观看 | 精品国产一二三 | 色多多在线观看 | 综合久久精品 | 亚洲做受高潮欧美裸体 | 免费国产在线精品 | 少妇视频一区 | a在线免费观看视频 | 欧美性做爰猛烈叫床潮 | 久草在线最新视频 | 一级精品视频在线观看宜春院 | 一区在线观看 | 国产日韩在线看 | 99精品视频免费观看 | 美女网站黄在线观看 | av在线观 | 亚洲欧美经典 | 丁香综合 | 狠狠的干狠狠的操 | 国内精品久久久精品电影院 | 日韩午夜一级片 | 精品美女在线视频 | 一级淫片在线观看 | 国产中文字幕在线免费观看 | 色噜噜狠狠狠狠色综合久不 | 五月天,com | 91尤物国产尤物福利在线播放 | 日韩中文字幕a | 国产一区二区三区久久久 | 国产精国产精品 | 午夜影院先 | 天干啦夜天干天干在线线 | 精品国产欧美一区二区三区不卡 | 久久久五月天 | 最新中文字幕在线资源 | 六月丁香社区 | 日韩视频在线一区 | 天天插伊人 | 欧美一区二区三区免费看 | av一级免费 | 97爱| 国产五十路毛片 | 日日夜夜天天综合 | 久久伊人国产精品 | 毛片888| 很污的网站 | 国产丝袜制服在线 | 高清一区二区三区av | 欧美极度另类性三渗透 | 成人毛片在线观看视频 | 欧美少妇的秘密 | 亚洲国产wwwccc36天堂 | 久久av免费电影 | 九色porny真实丨国产18 | 午夜私人影院久久久久 | 91亚洲精品在线观看 | 91精选在线 | 日韩免费视频播放 | 欧美黄色软件 | 久久综合色8888 | 久久一线 | 国产午夜精品久久 | 久久激情视频网 | 亚洲经典中文字幕 | 在线免费中文字幕 | 亚洲精品乱码白浆高清久久久久久 | 国产剧情久久 | 国产探花 | 婷色在线 | 天天色天天操天天爽 | 狠狠躁日日躁狂躁夜夜躁av | 91视频在线免费 | 色播六月天 | 中文字幕高清视频 | 国产一区二区三区免费观看视频 | 永久免费精品视频网站 | 免费观看一级一片 | 三级黄在线 | 毛片激情永久免费 | 在线观看免费视频你懂的 | 亚洲日本精品视频 | 欧美一区二区精品在线 | 久久av影视 | 国产亚洲精品成人av久久ww | 黄色软件在线观看免费 | 亚洲精品免费看 | 久久久精品国产免费观看同学 | 波多野结衣在线播放视频 | 狠狠干在线播放 | 久久久www | 狠狠躁夜夜躁人人爽超碰97香蕉 | 亚洲日本精品视频 | 日韩欧美在线观看一区二区三区 | 免费日韩视 | 国产精品涩涩屋www在线观看 | 欧美日韩伦理一区 | 日韩欧美国产视频 | 91麻豆精品国产91久久久无限制版 | 成年人免费在线观看网站 | 91丨精品丨蝌蚪丨白丝jk | 狠狠色噜噜狠狠狠狠 | 亚洲黄色在线看 | 日日夜夜天天干 | 成年人视频在线观看免费 | 99热精品国产一区二区在线观看 | 我要看黄色一级片 | 久精品在线观看 | 国内偷拍精品视频 | 色综合久久精品 | 91传媒91久久久| 久久免费成人网 | 999国内精品永久免费视频 | 国产99在线免费 | 欧美精品久久久久a | 亚洲成色777777在线观看影院 | 国产精品久久久久久久久大全 | 精品国产三级a∨在线欧美 免费一级片在线观看 | 久久午夜视频 | 亚洲一级片 | 亚洲艳情| 亚洲人精品午夜 | 成人禁用看黄a在线 | 中文字幕人成不卡一区 | 久久免费在线 | 久久嗨| 一区二区影院 | 午夜精品久久久久久久爽 | 久久这里只有精品23 | 国产成人精品一区二区三区福利 | 国产看片网站 | 欧美在线视频第一页 | 成年人在线免费看片 | 91色在线观看| 精品一区av | 99精品视频在线免费观看 | 中文字幕黄色av | 伊人视频 | 国产中文视 | 天天操夜操视频 | 五月天激情综合 | 久久免费视频网站 | 国产精品麻豆三级一区视频 | av在观看 | 国产高清成人 | 国产精彩在线视频 | 成人亚洲综合 | 欧美精品久久久久久久久免 | 99免在线观看免费视频高清 | 久久久久 | 色香蕉在线视频 | 久草a在线| 日韩视频免费观看高清 | 日韩r级在线 | 三级av在线播放 | 99热亚洲精品| 国产亚洲综合性久久久影院 | 日韩系列在线 | 亚洲国产精品电影在线观看 | 国内成人精品2018免费看 | 日韩中文字幕免费视频 | 91九色视频在线播放 | 欧美另类美少妇69xxxx | 久久国内精品视频 | 九九九九九九精品任你躁 | 成人av免费在线播放 | 美女一二三区 | 久久婷综合 | 免费看亚洲毛片 | 日韩在线视频免费播放 | 午夜精品一区二区三区免费视频 | 久久永久视频 | 国产剧情av在线播放 | 草久电影 | 久久综合免费视频影院 | 国产精品久久久久久久久久免费看 | 99免费看片 | 伊人久久国产 | 日韩av福利在线 | 成人午夜精品 | 国产精品久久精品 | 五月天色婷婷丁香 | 激情五月在线观看 | 亚洲综合少妇 | 91视频88av | 色狠狠一区二区 | 91av精品 | 免费一级片在线观看 | 日本在线精品视频 | 免费看三级黄色片 | 色狠狠一区二区 | 成人网中文字幕 | 免费碰碰| 亚洲免费在线观看视频 | 麻豆传媒视频在线播放 | 日韩欧美高清一区二区 | 精品麻豆入口免费 | 色偷偷88888欧美精品久久久 | 婷婷深爱激情 | 97免费中文视频在线观看 | 日本超碰在线 | 99视频在线免费观看 | 激情五月六月婷婷 | 欧美成人h版在线观看 | 久久 在线 | 天天操天天综合网 | 国产一线在线 | 日日爽夜夜爽 | 最近最新中文字幕视频 | 九九视频在线观看视频6 | 亚洲国产一区av | 欧美日韩中文另类 | 99视频这里有精品 | 久久99国产综合精品 | 精品国产免费久久 | 国产高清视频在线播放一区 | bbbb操bbbb| 91人人爱| 人人人爽 | 久久九九久久精品 | 国产精品免费久久久久久 | 色94色欧美 | 精品99免费 | 国产黄色免费在线观看 | 成人免费网站在线观看 | 成年人在线观看视频免费 | 日韩av电影手机在线观看 | 国产精品免费成人 | 久久99久久99久久 | 欧美精品做受xxx性少妇 | 国产精品99久久久久久大便 | 在线电影 一区 | 日本久久综合视频 | 欧美伦理一区二区 | 奇米影视8888在线观看大全免费 | 国产在线观看,日本 | 97超碰人人澡人人 | 成人国产一区二区 | 国产精品欧美一区二区 | 日韩免费观看一区二区 | 岛国av在线不卡 | 亚洲久久视频 | 久久久影院一区二区三区 | 这里有精品在线视频 | 久久久久综合视频 | 天天曰夜夜操 | 亚洲综合色激情五月 | 伊人网综合在线观看 | 中文字幕高清在线播放 | 中文字幕在线视频一区二区 | 日韩在线电影观看 | 亚洲在线看 | 亚洲成人家庭影院 | 91入口在线观看 | 五月婷婷狠狠 | av在线专区 | av亚洲产国偷v产偷v自拍小说 | 久久精品免费播放 | av丝袜制服 | 日韩有码在线观看视频 | 91看片淫黄大片一级在线观看 | 91精品蜜桃 | 97精品超碰一区二区三区 | 激情丁香5月 | 97超碰人人看 | 日韩色av色资源 | 日韩av免费一区 | 爱爱av网站| 亚洲国产精品免费 | 国产日韩欧美精品在线观看 | 欧美精品中文字幕亚洲专区 | 中国一级特黄毛片大片久久 | 综合久久久久久久 | 国产美女在线免费观看 | 九九久久久久久久久激情 | 在线免费观看涩涩 | av高清在线 | 欧美日韩在线观看视频 | 黄色国产在线观看 | 精品一区二区在线看 | 在线电影播放 | 麻豆免费在线播放 | 免费看色的网站 | 在线观看日韩精品 | 精品久久久久久久久久久久 | 欧美午夜精品久久久久 | 综合网天天色 | 久久一及片| 日韩欧美aaa| 久草网站 | 日韩二区精品 | 国产亚洲精品美女久久 | 波多野结衣在线观看一区 | 国产精品黄网站在线观看 | 97精品国自产拍在线观看 | 天天色成人 | 国产精品正在播放 | 久久精品久久久久久久 | 日韩91精品 | 精品女同一区二区三区在线观看 | 91视频在线观看下载 | 91污视频在线观看 | 在线播放视频一区 | 国产成人精品久久 | 97韩国电影| 欧美日韩国产精品一区 | 国产精品小视频网站 | 亚洲精品久久久久中文字幕m男 | 日韩av看片 | 国产精品大片在线观看 | 国产精品6999成人免费视频 | 美女久久久久久久久久 | 婷婷五月色综合 | 国产精品久久久久久久久蜜臀 | 日韩激情第一页 | 婷婷久月| 91探花国产综合在线精品 | 丁香婷婷电影 | 久久精品老司机 | 欧美精彩视频在线观看 | 中文字幕在线不卡国产视频 | 懂色av一区二区在线播放 | 99热在线国产精品 | 国产精品国产三级国产 | 国产精品视频一二三 | 欧美午夜精品久久久久久浪潮 | 亚洲黄色免费电影 | 美女久久 | 伊人天堂av | 国产资源| 91亚洲精品视频 | 日韩av手机在线观看 | 色婷婷在线播放 | 国产成人精品亚洲精品 | 天天操人人干 | 在线免费观看的av | 天天激情| 97在线免费观看视频 | 久久精品99国产精品亚洲最刺激 | 精品国产乱码久久久久久天美 | 久久视频一区 | 久久人人艹| 国产色视频一区二区三区qq号 | 麻豆视屏 | 国产在线观看免费 | 天天色宗合 | 久久久久国产一区二区三区四区 | 亚洲欧美日本一区二区三区 | 亚洲一区二区视频在线播放 | 超碰在97| 久久9视频 | 九草视频在线 | 美女黄视频免费看 | 久久99国产精品久久99 | 久久国产经典视频 | 国产欧美综合在线观看 | 国产小视频在线免费观看视频 | 手机av在线网站 | 四虎在线视频免费观看 | 99精品视频播放 | 伊人永久在线 | 视频国产区| 精品在线视频播放 | 中国一级片在线观看 | 国产精品嫩草影视久久久 | 99久久国产免费免费 | 久久精品韩国 | 激情五月六月婷婷 | 日韩毛片精品 | 久久久96 | 日韩中文字幕免费在线观看 | 国产黄色片免费看 | 国产精品区免费视频 | 亚洲黄色一级电影 | 久久超| 久久久精品免费看 | 国产视频午夜 | 美女视频一区 | 黄色在线免费观看网站 | 最近中文字幕免费av | 国产二区视频在线 | 91成人天堂久久成人 | 九九久久精品视频 | 狠狠狠色狠狠色综合 | 亚洲视频 在线观看 | 国产精品久久久久久久7电影 | 成人免费xyz网站 | 国产精品一区二区av影院萌芽 | 不卡中文字幕av | 久久久久免费精品 | 国产中文字幕视频在线观看 | 麻豆你懂的 | 国产精品一区二区久久精品 | 五月开心婷婷 | 91九色视频在线 | 亚洲国产影院av久久久久 | 精品视频一区在线观看 | 日韩理论视频 | 欧美日韩伦理在线 | 国产精品美女www爽爽爽视频 | 国产精品久久久久永久免费 | 成人黄在线观看 | 91av电影在线观看 | 国产精品一区二区久久国产 | 日本系列中文字幕 | 特级毛片在线免费观看 | 免费看一及片 | 久久久999 | 国产黄色一级大片 | 国产午夜不卡 | 日韩com | 不卡的av片 | 久久人人做 | 91精品一区二区三区蜜臀 | 4hu视频| 色先锋资源网 | 久久久久国产一区二区三区四区 | 亚洲,国产成人av | 午夜久久福利视频 | 久久不卡日韩美女 | 久久夜色网 | 天天操网站 | 天堂视频中文在线 | 国产精品久久久久久久久久久免费 | 日韩精品在线观看视频 | 久久9999久久| 午夜久久电影网 | 97人人射 | 国产高清视频色在线www | 欧美a在线免费观看 | 最近中文字幕完整视频高清1 | 欧美一二三区在线播放 | 久久国语 | 免费观看成人网 | 怡红院av | av不卡网站| 国产高清小视频 | 日韩精品1区2区 | av动图 | 男女免费视频观看 | www.成人sex| 色婷婷久久 | 精品一区电影国产 | 欧美日bb| 成 人 黄 色 免费播放 | 日韩视频免费在线观看 | 91丨九色丨蝌蚪丰满 | 免费黄色网址网站 | 91精品一区二区在线观看 | 精品亚洲在线 | 在线观看中文字幕 | 人人射网站 | 亚洲无在线 | 久久爱资源网 | 国产精选在线观看 | 五月综合在线观看 | 久久精品国产免费看久久精品 | 欧美激情精品久久久久久 | 国产一区免费观看 | 热久久99这里有精品 | 欧美一区二区日韩一区二区 | 久久视频在线 | 91超碰免费在线 | 一区二区欧美激情 | 99亚洲国产 | 久久不色 | 91九色自拍 | 超碰国产97 | 视频二区在线 | 一区二区不卡在线观看 | 在线91观看| 久久在线免费观看视频 | 2019天天干夜夜操 | 天天se天天cao天天干 | 91正在播放 | 最新国产在线视频 | 香蕉视频在线网站 | 国产午夜一区二区 | 97超碰国产在线 | 午夜视频在线观看一区二区三区 | 一区二区亚洲精品 | 一区二区三区在线影院 | 91视频国产免费 | 欧美日韩中文国产一区发布 | 国产一二三四在线观看视频 | 欧美午夜精品久久久久久浪潮 | 波多野结衣视频网址 | 99久久精品无码一区二区毛片 | 91福利免费| 久久精品一二三区白丝高潮 | 国产小视频在线播放 | 99re亚洲国产精品 | 亚洲成人黄色av | 免费在线观看av网址 | 国产98色在线 | 日韩 | 丁香综合av | 91精品视频在线免费观看 | 亚洲成人网在线 | 911久久| 九九九国产 | 久色小说 | 国产黄色在线网站 | 色婷婷丁香| 日本午夜在线亚洲.国产 | 日日操操操 | 日韩成人免费观看 | 99在线免费视频 | 外国av网 | 中文字幕欲求不满 | 国产中文a | 国产日韩欧美网站 | 午夜精品一区二区国产 | 国产成人精品久久久久蜜臀 | 人人爽人人乐 | 精品一区二区av | 久久女教师 | 91福利国产在线观看 | 亚洲精品国产精品国自产观看 | 久久er99热精品一区二区三区 | 亚洲精品在线免费播放 | 久久精品牌麻豆国产大山 | 欧美日韩在线免费视频 | 精品国产伦一区二区三区观看说明 | 岛国av在线免费 | 日日干,天天干 | 天天干天天玩天天操 | 久久96国产精品久久99软件 | 成人黄色小说网 | 五月婷社区 | 国内久久久 | 久久伊人婷婷 | 欧美乱码精品一区 | 日韩在线观看一区二区三区 | 福利视频导航网址 | 日日夜夜精品网站 | 69av视频在线 | 天天爱天天色 | 欧美天天射 | 精品久久精品久久 | 色偷偷人人澡久久超碰69 | 国产小视频免费在线网址 | 人人射人人爱 | 国产精品国产三级国产不产一地 | 欧美日韩国语 | 日韩欧美一区二区在线观看 | 久久综合给合久久狠狠色 | 免费视频黄 | 久久免费一级片 | 黄色国产区 | 欧美在线一二区 | 亚洲禁18久人片 | 成人精品国产免费网站 | 欧美淫aaa免费观看 日韩激情免费视频 | av网址在线播放 | 精品二区久久 | 色99视频 | 免费影视大全推荐 | 人人爽人人干 | 色姑娘综合天天 | 免费国产在线精品 | 免费成人av在线看 | 激情欧美一区二区三区 | 在线 高清 中文字幕 | 精品国产一区二区三区久久影院 | 日韩精品第1页 | 日韩在线观看你懂的 | 亚洲成a人片在线观看网站口工 | 久久av免费电影 | 麻豆网站免费观看 | 干综合网| 久久免费观看视频 | 欧美男同网站 | 国产麻豆精品一区 | 在线观看免费 | 麻豆91在线观看 | 国产精品123 | 日日夜夜噜噜噜 | 色偷偷88888欧美精品久久 | a级片久久久| 国产手机在线观看视频 | 免费进去里的视频 | 精品国产欧美一区二区 | 国产精品免费一区二区三区 | 日韩欧三级 | 99热只有精品在线观看 | 国产午夜精品一区二区三区在线观看 | 天天操夜夜操天天射 | 久久香蕉影视 | 亚洲成熟女人毛片在线 | 操高跟美女 | 久久久久高清毛片一级 | 亚洲激情电影在线 | 国产xx在线| 国产精品久久二区 | www.在线观看av| 天天操狠狠操夜夜操 | 一区二区三区动漫 | 国产成人精品久久二区二区 | 狠狠狠狠狠色综合 | 亚洲国产精品va在线 | 欧美一区二区伦理片 | 午夜久久网站 | 久久免费视频99 | 一本—道久久a久久精品蜜桃 | 日韩精品一区二区在线视频 | 亚洲精品一区二区三区高潮 | 欧美精品久久久久性色 | 黄p网站在线观看 | 激情网综合 | 欧美午夜精品久久久久久浪潮 | 日韩免费播放 | 一本一道波多野毛片中文在线 | 亚洲天堂网在线播放 | 欧美日韩一区二区三区在线观看视频 | 日日弄天天弄美女bbbb | 黄色免费电影网站 | 91日韩精品一区 | 女人久久久久 | 伊人在线视频 | 99久免费精品视频在线观看 | 中文字幕亚洲在线观看 | 日韩欧美xxxx | 一区二区三高清 | 麻豆mv在线观看 | 九九免费在线观看视频 | 日韩电影一区二区在线观看 | 亚洲精品国产综合久久 | 天天操天天谢 | 三级av在线免费观看 | 中文字幕高清在线播放 | 国产精品岛国久久久久久久久红粉 | www.五月天色 | 国产精品一区二区三区久久 | 久久综合加勒比 | 一级黄色网址 | 国产乱对白刺激视频在线观看女王 | 天堂av观看 | 一级片免费观看 | 久久国产精品色婷婷 | 夜夜爽www| 91视频在线免费看 | 精品国产免费人成在线观看 | 久久精品第一页 | 高清免费在线视频 | 九九九视频精品 | 欧美激情综合五月色丁香 | 国产日韩欧美在线一区 | 五月婷婷激情 | 国产高清在线免费观看 | 五月婷社区 | 日韩簧片在线观看 | 日韩精品中文字幕一区二区 | 亚洲国产精品久久久久久 | 一区二区中文字幕在线 | 国产视频在线观看一区二区 | 国产成视频在线观看 | 韩国av在线播放 | 天天干天天操天天 | 日本久久片 | 激情五月在线视频 | 国产精品美女久久久免费 | 西西444www大胆无视频 | 麻花豆传媒一二三产区 | 欧美一级在线观看视频 | 国产视频资源在线观看 | 国产又黄又爽无遮挡 | 五月婷婷影院 | 在线精品一区二区 | 国产中文字幕久久 | 美女黄频 | 天堂在线一区二区 | 中文字幕.av.在线 | 美女网站在线免费观看 | 很黄很黄的网站免费的 | 久草网在线视频 | 黄色成人在线 | 三级av在线免费观看 | 美女性爽视频国产免费app | 国产精品精品久久久久久 | 日本99热| 亚洲国产剧情 | 久久久久免费精品国产小说色大师 | 成人免费在线视频观看 | 一区二区不卡视频在线观看 | 五月天国产 | 国产精品免费视频久久久 | 国产午夜一区二区 | 国产精品成人久久久久 | 成人av免费电影 | 亚洲狠狠操 | 亚洲午夜不卡 | 久久国产精品精品国产色婷婷 | 免费观看www7722午夜电影 | 国产在线va| 91精品婷婷国产综合久久蝌蚪 | 成人影视免费 | 日韩久久精品一区二区 | 久久99在线| 99久久婷婷国产 | 精品一区二区在线播放 | 亚洲成色777777在线观看影院 | 麻豆视频成人 | 国产视频一 | 亚洲国产高清在线 | 欧美精品久久久久a | 久久久网址 | 大荫蒂欧美视频另类xxxx | 久久成人高清视频 | 免费在线观看黄色网 | 在线导航福利 | 开心丁香婷婷深爱五月 | 久久激情五月婷婷 | 国产无区一区二区三麻豆 | 欧美男女爱爱视频 | 丁香六月在线观看 | 91女子私密保健养生少妇 | 九色91在线视频 | 天干啦夜天干天干在线线 | av不卡网站 | 欧美一级性生活视频 | 成人免费观看网站 | 婷婷综合伊人 | 国产高清av免费在线观看 | 久久高清毛片 | 日本电影久久 | 日日夜日日干 | 国产一级视频在线免费观看 | 97国产 | 久久99精品久久只有精品 | 夜色在线资源 | 久久综合五月 | 国产一区二区高清不卡 | 成人在线视频论坛 | 超碰人人做 | 中文字幕频道 | 欧美一级片在线观看视频 | 久久精品第一页 | 日日精品 | 国产精品久久久久一区二区三区 | 乱子伦av| 天天天天天天干 | 久久资源在线 | 亚洲日本中文字幕在线观看 | 免费色视频| 国产成人一区三区 | 精品久久久久久久久久国产 | 久久这里只有精品9 | 国产一区久久久 | 狠狠干综合 | 69视频在线播放 | 国产视频在线观看免费 | 欧美一二三区在线观看 | 色七七亚洲影院 | 97人人澡人人添人人爽超碰 | 亚洲影视九九影院在线观看 | 91久久偷偷做嫩草影院 | 婷婷视频在线播放 | 一区二区毛片 | 激情喷水 | 成人黄色免费观看 | wwwwww色| 日韩欧美国产精品 | 99精品国产高清在线观看 | 久久这里有 | 久久国产精品一区二区 | 在线观看成人小视频 | 国产 日韩 在线 亚洲 字幕 中文 | 成人蜜桃 | 日韩免费区 | 在线观看免费视频 | 99免费精品 | 91九色视频国产 | 国产色啪 | 人人看黄色 | 日p视频在线观看 | 国产精品原创av片国产免费 | 玖玖玖在线观看 | 成人黄在线观看 | 色 免费观看 | 韩国精品福利一区二区三区 | 狠狠躁天天躁综合网 | 亚洲精品视频大全 | 免费观看国产精品 | 日本三级大片 | 日本中文字幕在线观看 | 999日韩 | 欧美日韩在线视频观看 | 精品毛片一区二区免费看 | 九九九九免费视频 | 丰满少妇一级 | 国产成人a v电影 | 天天天色| 午夜久久美女 | 99久久精品无免国产免费 | 精品麻豆入口免费 | 超碰免费av | 综合成人在线 | 免费一区在线 | 波多野结衣视频一区二区三区 | 日韩精品久久久久久久电影99爱 | 97av影院| 久久亚洲在线 | 在线免费观看麻豆 | 国产破处在线视频 | 日韩欧美在线视频一区二区 | 在线国产91 | 草久在线观看视频 | 最近免费中文字幕 | 亚洲 综合 精品 | 久久激五月天综合精品 | 顶级bbw搡bbbb搡bbbb | 国产又粗又硬又爽的视频 | 久久免费高清 | 国产精品一区二区三区在线看 | 97在线免费观看 | 午夜av片| 99在线精品视频在线观看 | 午夜少妇一区二区三区 | 亚洲九九九在线观看 | 日韩午夜在线观看 | 天天射天天操天天 | 日韩欧美电影在线 | 波多野结衣动态图 | 菠萝菠萝在线精品视频 | 日韩免费av网址 | 免费91在线观看 | 亚洲国产av精品毛片鲁大师 | 成人久久精品 | 中文字幕网站视频在线 | 精品久久九九 | 美州a亚洲一视本频v色道 | 久青草国产在线 | 国产精品免费久久 | 日本精品久久久久 | 成人久久18免费网站图片 | 久久综合九色综合欧美就去吻 | 一级黄色在线免费观看 | av解说在线观看 | av在线一| 色网影音先锋 | 亚洲精品影视在线观看 | 精品在线视频观看 | 成年美女黄网站色大片免费看 | 岛国av在线 | 日本韩国精品在线 | 国产精品毛片一区二区在线看 | 国产精品99久久久久人中文网介绍 | 久久er99热精品一区二区三区 | www.com操 | 播五月婷婷 | 黄色aa久久 | 亚洲高清在线精品 | 91视频在线观看大全 | 国产成人无码AⅤ片在线观 日韩av不卡在线 | 久久久91精品国产一区二区精品 | 久久热亚洲 | 色网站在线 | 国产精品成人免费一区久久羞羞 | 亚洲国产综合在线 | 国产在线一区二区 | 精品久久一二三区 | 天天草天天干天天 | 国产免费中文字幕 | 中文国产在线观看 | 日韩免费在线视频 | 99精品视频在线观看视频 | 97超碰资源站 | 91成人精品一区在线播放69 | 亚洲国产合集 | 九九热精品视频在线播放 | 久久国产午夜精品理论片最新版本 | 天天爱天天射天天干天天 | 亚洲成av人片在线观看 | 精品国产精品久久 | 在线免费观看黄色av | 91一区二区三区久久久久国产乱 | 伊人久操 | 五月婷婷另类国产 | 99精品偷拍视频一区二区三区 | 99日精品 | 伊人国产女 | 91精品在线观看视频 | 91豆花在线观看 | 免费能看的黄色片 | 日韩69视频| 四虎影视精品成人 | 国产女人18毛片水真多18精品 | 久久精品国产一区二区三区 | 免费视频xnxx com | 91人人人| 人人添人人澡人人澡人人人爽 | 久久精品中文字幕免费mv | 亚洲精品88欧美一区二区 | av成人在线看 | 69精品视频 | 日韩视频在线一区 | 最近中文字幕高清字幕免费mv | 亚洲高清在线 | 久久九九久久精品 | 久久露脸国产精品 | 日本免费久久高清视频 | 国产精品国产三级国产aⅴ无密码 | 国产一区精品在线 | 色偷偷97| 日韩a级免费视频 | 在线视频久 | 色综合久久久久久久 | 天天激情综合 | 911香蕉视频 | www日韩精品 | 狠狠狠色丁香婷婷综合久久五月 | 欧美日韩亚洲在线 | 国产破处在线视频 | avwww在线| 久久久久麻豆v国产 | 中文字幕在线国产 | 日韩免费电影在线观看 | 麻花天美星空视频 | 欧美午夜精品久久久久 | 久色 网| 一本一道久久a久久精品 | 青青草国产成人99久久 | 96国产在线 | 久久亚洲免费 |