這篇文章想寫的是,在各種場合里學(xué)到的厢洞,聽到了一些新東西仇让,新名詞典奉。或者是別人很懂丧叽,但是對于我來說是新接觸的東西卫玖。打算把他們記在這里。
1. 驚群效應(yīng)
最常見的例子就是對于socket描述符的accept操作踊淳,當(dāng)多個用戶進(jìn)程/線程監(jiān)聽在同一個端口上時假瞬,由于實際只可能accept一次,因此就會產(chǎn)生驚群現(xiàn)象迂尝。
也就是說脱茉,多個子進(jìn)程都會阻塞在accept函數(shù)那邊,然后一個鏈接過來垄开,所有的子進(jìn)程調(diào)用的accpet都返回了琴许。但是只有其中的一個是返回成功的。其他的都是-1溉躲。
這個問題是一個古老的問題榜田,但目前的內(nèi)核版本已經(jīng)修復(fù)了這個問題,
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <unistd.h>
int main()
{
int listenfd;
pid_t parentid, childid;
struct sockaddr_in servaddr;
int forknum = 10;
short port = 9527;
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(port);
listenfd = socket(AF_INET, SOCK_STREAM, 0);
int res = bind(listenfd, (sockaddr *)&servaddr, sizeof(sockaddr_in));
if (0 == res)
printf("server bind success, port:%d\n", port);
else {
printf("server bind fail!\n");
exit(-1);
}
res = listen(listenfd, 100);
if (0 == res)
printf("server listen success!\n");
else {
printf("server listen fail!\n");
exit(-1);
}
parentid = getpid();
//創(chuàng)建10個子進(jìn)程
for (int i=0; i<forknum; ++i) {
if (getpid() == parentid) {
childid = fork();
if (0 == childid)
printf("the parentid is %d, chlidid is %d\n", getppid(), getpid());
}
}
//10個子進(jìn)程都在accept锻梳,但是如果一個連接來了
//10個子進(jìn)程都會一但有客戶端連接箭券,所有進(jìn)程的accept()都會返回,
//但是只有一個進(jìn)程會accept成功疑枯,就是驚群辩块。
//but linux 2.6 內(nèi)核 解決了這個問題
for (; ;) {
int connfd = accept(listenfd, NULL, NULL);
if (connfd != -1)
printf("the pid is %d, connfd is %d\n", getpid(), connfd);
}
}
輸出結(jié)果: (沒有出現(xiàn)驚群效應(yīng))
linux 是如何解決的:
1.Linux2.6在內(nèi)核級別讓accept成為原子操作,如果多個進(jìn)程同時阻塞在accept上神汹,每次僅喚醒等待隊列的第一個進(jìn)程從accept返回并拿到用戶連接庆捺。
2.問題是,在實際生產(chǎn)環(huán)境中屁魏,通常是先用select/epoll來監(jiān)聽listen_fd是否有連接過來滔以,再調(diào)用accept,也就是說驚群點從accept提前到epoll上了氓拼。
3.Nginx的解決方案是你画,設(shè)置一把全局accpet鎖,每個進(jìn)程先去競爭這把鎖桃漾,拿到鎖的進(jìn)程才向epoll中注冊listen_fd事件坏匪。
參考:
https://blog.csdn.net/tuantuanls/article/details/41205739
https://www.zhihu.com/question/22756773
2. 從匯編的角度理解引用
int x = 1;
int y = 2;
int &b = x;
也就是說,b里面存放的是x的地址撬统。C++中引用是編譯器通過指針實現(xiàn)的适滓,但這個實現(xiàn)在語言層面對程序員做了透明化處理。
參考:
https://blog.csdn.net/wanwenweifly4/article/details/6739687