⑴ 環評中CP、EP的意思
CP是指以污染為主的建設項目;EP是指以生態破壞為主的建設項目;EI是指環境影響
⑵ 面試必問的epoll技術,從內核源碼出發徹底搞懂epoll
epoll是linux中IO多路復用的一種機制,I/O多路復用就是通過一種機制,一個進程可以監視多個描述符,一旦某個描述符就緒(一般是讀就緒或者寫就緒),能夠通知程序進行相應的讀寫操作。當然linux中IO多路復用不僅僅是epoll,其他多路復用機制還有select、poll,但是接下來介紹epoll的內核實現。
events可以是以下幾個宏的集合:
epoll相比select/poll的優勢 :
epoll相關的內核代碼在fs/eventpoll.c文件中,下面分別分析epoll_create、epoll_ctl和epoll_wait三個函數在內核中的實現,分析所用linux內核源碼為4.1.2版本。
epoll_create用於創建一個epoll的句柄,其在內核的系統實現如下:
sys_epoll_create:
可見,我們在調用epoll_create時,傳入的size參數,僅僅是用來判斷是否小於等於0,之後再也沒有其他用處。
整個函數就3行代碼,真正的工作還是放在sys_epoll_create1函數中。
sys_epoll_create -> sys_epoll_create1:
sys_epoll_create1 函數流程如下:
sys_epoll_create -> sys_epoll_create1 -> ep_alloc:
sys_epoll_create -> sys_epoll_create1 -> ep_alloc -> get_unused_fd_flags:
linux內核中,current是個宏,返回的是一個task_struct結構(我們稱之為進程描述符)的變數,表示的是當前進程,進程打開的文件資源保存在進程描述符的files成員裡面,所以current->files返回的當前進程打開的文件資源。rlimit(RLIMIT_NOFILE) 函數獲取的是當前進程可以打開的最大文件描述符數,這個值可以設置,默認是1024。
相關視頻推薦:
支撐億級io的底層基石 epoll實戰揭秘
網路原理tcp/udp,網路編程epoll/reactor,面試中正經「八股文」
學習地址:C/C++Linux伺服器開發/後台架構師【零聲教育】-學習視頻教程-騰訊課堂
需要更多C/C++ Linux伺服器架構師學習資料加群 812855908 獲取(資料包括C/C++,Linux,golang技術,Nginx,ZeroMQ,MySQL,Redis,fastdfs,MongoDB,ZK,流媒體,CDN,P2P,K8S,Docker,TCP/IP,協程,DPDK,ffmpeg等),免費分享
__alloc_fd的工作是為進程在[start,end)之間(備註:這里start為0, end為進程可以打開的最大文件描述符數)分配一個可用的文件描述符,這里就不繼續深入下去了,代碼如下:
sys_epoll_create -> sys_epoll_create1 -> ep_alloc -> get_unused_fd_flags -> __alloc_fd:
然後,epoll_create1會調用anon_inode_getfile,創建一個file結構,如下:
sys_epoll_create -> sys_epoll_create1 -> anon_inode_getfile:
anon_inode_getfile函數中首先會alloc一個file結構和一個dentry結構,然後將該file結構與一個匿名inode節點anon_inode_inode掛鉤在一起,這里要注意的是,在調用anon_inode_getfile函數申請file結構時,傳入了前面申請的eventpoll結構的ep變數,申請的file->private_data會指向這個ep變數,同時,在anon_inode_getfile函數返回來後,ep->file會指向該函數申請的file結構變數。
簡要說一下file/dentry/inode,當進程打開一個文件時,內核就會為該進程分配一個file結構,表示打開的文件在進程的上下文,然後應用程序會通過一個int類型的文件描述符來訪問這個結構,實際上內核的進程裡面維護一個file結構的數組,而文件描述符就是相應的file結構在數組中的下標。
dentry結構(稱之為「目錄項」)記錄著文件的各種屬性,比如文件名、訪問許可權等,每個文件都只有一個dentry結構,然後一個進程可以多次打開一個文件,多個進程也可以打開同一個文件,這些情況,內核都會申請多個file結構,建立多個文件上下文。但是,對同一個文件來說,無論打開多少次,內核只會為該文件分配一個dentry。所以,file結構與dentry結構的關系是多對一的。
同時,每個文件除了有一個dentry目錄項結構外,還有一個索引節點inode結構,裡面記錄文件在存儲介質上的位置和分布等信息,每個文件在內核中只分配一個inode。 dentry與inode描述的目標是不同的,一個文件可能會有好幾個文件名(比如鏈接文件),通過不同文件名訪問同一個文件的許可權也可能不同。dentry文件所代表的是邏輯意義上的文件,記錄的是其邏輯上的屬性,而inode結構所代表的是其物理意義上的文件,記錄的是其物理上的屬性。dentry與inode結構的關系是多對一的關系。
sys_epoll_create -> sys_epoll_create1 -> fd_install:
總結epoll_create函數所做的事:調用epoll_create後,在內核中分配一個eventpoll結構和代表epoll文件的file結構,並且將這兩個結構關聯在一塊,同時,返回一個也與file結構相關聯的epoll文件描述符fd。當應用程序操作epoll時,需要傳入一個epoll文件描述符fd,內核根據這個fd,找到epoll的file結構,然後通過file,獲取之前epoll_create申請eventpoll結構變數,epoll相關的重要信息都存儲在這個結構裡面。接下來,所有epoll介面函數的操作,都是在eventpoll結構變數上進行的。
所以,epoll_create的作用就是為進程在內核中建立一個從epoll文件描述符到eventpoll結構變數的通道。
epoll_ctl介面的作用是添加/修改/刪除文件的監聽事件,內核代碼如下:
sys_epoll_ctl:
根據前面對epoll_ctl介面的介紹,op是對epoll操作的動作(添加/修改/刪除事件),ep_op_has_event(op)判斷是否不是刪除操作,如果op != EPOLL_CTL_DEL為true,則需要調用_from_user函數將用戶空間傳過來的event事件拷貝到內核的epds變數中。因為,只有刪除操作,內核不需要使用進程傳入的event事件。
接著連續調用兩次fdget分別獲取epoll文件和被監聽文件(以下稱為目標文件)的file結構變數(備註:該函數返回fd結構變數,fd結構包含file結構)。
接下來就是對參數的一些檢查,出現如下情況,就可以認為傳入的參數有問題,直接返回出錯:
當然下面還有一些關於操作動作如果是添加操作的判斷,這里不做解釋,比較簡單,自行閱讀。
在ep裡面,維護著一個紅黑樹,每次添加註冊事件時,都會申請一個epitem結構的變數表示事件的監聽項,然後插入ep的紅黑樹裡面。在epoll_ctl裡面,會調用ep_find函數從ep的紅黑樹裡面查找目標文件表示的監聽項,返回的監聽項可能為空。
接下來switch這塊區域的代碼就是整個epoll_ctl函數的核心,對op進行switch出來的有添加(EPOLL_CTL_ADD)、刪除(EPOLL_CTL_DEL)和修改(EPOLL_CTL_MOD)三種情況,這里我以添加為例講解,其他兩種情況類似,知道了如何添加監聽事件,其他刪除和修改監聽事件都可以舉一反三。
為目標文件添加監控事件時,首先要保證當前ep裡面還沒有對該目標文件進行監聽,如果存在(epi不為空),就返回-EEXIST錯誤。否則說明參數正常,然後先默認設置對目標文件的POLLERR和POLLHUP監聽事件,然後調用ep_insert函數,將對目標文件的監聽事件插入到ep維護的紅黑樹裡面:
sys_epoll_ctl -> ep_insert:
前面說過,對目標文件的監聽是由一個epitem結構的監聽項變數維護的,所以在ep_insert函數裡面,首先調用kmem_cache_alloc函數,從slab分配器裡面分配一個epitem結構監聽項,然後對該結構進行初始化,這里也沒有什麼好說的。我們接下來看ep_item_poll這個函數調用:
sys_epoll_ctl -> ep_insert -> ep_item_poll:
ep_item_poll函數裡面,調用目標文件的poll函數,這個函數針對不同的目標文件而指向不同的函數,如果目標文件為套接字的話,這個poll就指向sock_poll,而如果目標文件為tcp套接字來說,這個poll就是tcp_poll函數。雖然poll指向的函數可能會不同,但是其作用都是一樣的,就是獲取目標文件當前產生的事件位,並且將監聽項綁定到目標文件的poll鉤子裡面(最重要的是注冊ep_ptable_queue_proc這個poll callback回調函數),這步操作完成後,以後目標文件產生事件就會調用ep_ptable_queue_proc回調函數。
接下來,調用list_add_tail_rcu將當前監聽項添加到目標文件的f_ep_links鏈表裡面,該鏈表是目標文件的epoll鉤子鏈表,所有對該目標文件進行監聽的監聽項都會加入到該鏈表裡面。
然後就是調用ep_rbtree_insert,將epi監聽項添加到ep維護的紅黑樹裡面,這里不做解釋,代碼如下:
sys_epoll_ctl -> ep_insert -> ep_rbtree_insert:
前面提到,ep_insert有調用ep_item_poll去獲取目標文件產生的事件位,在調用epoll_ctl前這段時間,可能會產生相關進程需要監聽的事件,如果有監聽的事件產生,(revents & event->events 為 true),並且目標文件相關的監聽項沒有鏈接到ep的准備鏈表rdlist裡面的話,就將該監聽項添加到ep的rdlist准備鏈表裡面,rdlist鏈接的是該epoll描述符監聽的所有已經就緒的目標文件的監聽項。並且,如果有任務在等待產生事件時,就調用wake_up_locked函數喚醒所有正在等待的任務,處理相應的事件。當進程調用epoll_wait時,該進程就出現在ep的wq等待隊列裡面。接下來講解epoll_wait函數。
總結epoll_ctl函數:該函數根據監聽的事件,為目標文件申請一個監聽項,並將該監聽項掛人到eventpoll結構的紅黑樹裡面。
epoll_wait等待事件的產生,內核代碼如下:
sys_epoll_wait:
首先是對進程傳進來的一些參數的檢查:
參數全部檢查合格後,接下來就調用ep_poll函數進行真正的處理:
sys_epoll_wait -> ep_poll:
ep_poll中首先是對等待時間的處理,timeout超時時間以ms為單位,timeout大於0,說明等待timeout時間後超時,如果timeout等於0,函數不阻塞,直接返回,小於0的情況,是永久阻塞,直到有事件產生才返回。
當沒有事件產生時((!ep_events_available(ep))為true),調用__add_wait_queue_exclusive函數將當前進程加入到ep->wq等待隊列裡面,然後在一個無限for循環裡面,首先調用set_current_state(TASK_INTERRUPTIBLE),將當前進程設置為可中斷的睡眠狀態,然後當前進程就讓出cpu,進入睡眠,直到有其他進程調用wake_up或者有中斷信號進來喚醒本進程,它才會去執行接下來的代碼。
如果進程被喚醒後,首先檢查是否有事件產生,或者是否出現超時還是被其他信號喚醒的。如果出現這些情況,就跳出循環,將當前進程從ep->wp的等待隊列裡面移除,並且將當前進程設置為TASK_RUNNING就緒狀態。
如果真的有事件產生,就調用ep_send_events函數,將events事件轉移到用戶空間裡面。
sys_epoll_wait -> ep_poll -> ep_send_events:
ep_send_events沒有什麼工作,真正的工作是在ep_scan_ready_list函數裡面:
sys_epoll_wait -> ep_poll -> ep_send_events -> ep_scan_ready_list:
ep_scan_ready_list首先將ep就緒鏈表裡面的數據鏈接到一個全局的txlist裡面,然後清空ep的就緒鏈表,同時還將ep的ovflist鏈表設置為NULL,ovflist是用單鏈表,是一個接受就緒事件的備份鏈表,當內核進程將事件從內核拷貝到用戶空間時,這段時間目標文件可能會產生新的事件,這個時候,就需要將新的時間鏈入到ovlist裡面。
僅接著,調用sproc回調函數(這里將調用ep_send_events_proc函數)將事件數據從內核拷貝到用戶空間。
sys_epoll_wait -> ep_poll -> ep_send_events -> ep_scan_ready_list -> ep_send_events_proc:
ep_send_events_proc回調函數循環獲取監聽項的事件數據,對每個監聽項,調用ep_item_poll獲取監聽到的目標文件的事件,如果獲取到事件,就調用__put_user函數將數據拷貝到用戶空間。
回到ep_scan_ready_list函數,上面說到,在sproc回調函數執行期間,目標文件可能會產生新的事件鏈入ovlist鏈表裡面,所以,在回調結束後,需要重新將ovlist鏈表裡面的事件添加到rdllist就緒事件鏈表裡面。
同時在最後,如果rdlist不為空(表示是否有就緒事件),並且由進程等待該事件,就調用wake_up_locked再一次喚醒內核進程處理事件的到達(流程跟前面一樣,也就是將事件拷貝到用戶空間)。
到這,epoll_wait的流程是結束了,但是有一個問題,就是前面提到的進程調用epoll_wait後會睡眠,但是這個進程什麼時候被喚醒呢?在調用epoll_ctl為目標文件注冊監聽項時,對目標文件的監聽項注冊一個ep_ptable_queue_proc回調函數,ep_ptable_queue_proc回調函數將進程添加到目標文件的wakeup鏈表裡面,並且注冊ep_poll_callbak回調,當目標文件產生事件時,ep_poll_callbak回調就去喚醒等待隊列裡面的進程。
總結一下epoll該函數: epoll_wait函數會使調用它的進程進入睡眠(timeout為0時除外),如果有監聽的事件產生,該進程就被喚醒,同時將事件從內核裡面拷貝到用戶空間返回給該進程。
⑶ 股票軟體ep[動] 是什麼意思
股票軟體ep[動] 是動態市盈率
動態市盈率等於每股股價/(一季報每股收益*4)
市盈率對長線選股是個很好的參考指標
應該知識可以鏈接http://ke..com/view/287.htm
⑷ 求一個EP分銷系統源碼,easypanel(idc分銷系統
天下沒有免費的午餐,即使有免費的給你用,說不定源碼裡面被植入了木馬,還會篡改你的會員信息,修改會員余額,直接入侵財務賬戶。
⑸ 吉利汽車的商務政策文件里有個「EP指標」,請問是什麼東西
Environmental Protection,環境保護。環境保護是指人類為解決現實的或潛在的環境問題,協調人類與環境的關系,保障經濟社會的持續發展而採取的指標
⑹ 什麼是EP投資
在金融領域里!只聽過PE比較多,如果你確定的EP的話,可能就是我們談話中一些漢字拼音的縮寫!
PE的介紹可以給你!
PE可能是指:
私募股權投資(Private Equity,簡稱「PE」)在中國通常稱為私募股權投資,從投資方式角度看,依國外相關研究機構定義,是指通過私募形式對私有企業,即非上市企業進行的權益性投資,在交易實施過程中附帶考慮了將來的退出機制,即通過上市、並購或管理層回購等方式,出售持股獲利。如:PE基金投資
市盈率(Price/Earnings,簡稱「PE」),也稱為:本益比,價格收益比(Price/Earnings Ratio,PER)市盈率是最常用來評估股價水平是否合理的指標之一,由股價除以年度每股盈餘(EPS)得出(以公司市值除以年度股東應占溢利亦可得出相同結果)。
⑺ 關於股指期貨的SAR、CCI、BIAS、ATR指標的演算法
股指期貨中的周期指標除了SMA、EMA、BOOL、MACD、KDJ等還有很多其他分析的指標,如SAR、CCI、BIAS、ATR有時候也會被交易者用來判斷股指期貨的走向。正好最近項目中有需要加上這幾種指標供用戶使用,在此記錄一下:
在計算SAR之前,先要選定一段周期,比如n日或n周等,n天或周的參數一般為4日或4周。
計算Tn周期的SAR值為例,計算公式如下:
SAR(Tn)=SAR(Tn-1)+AF(Tn)*[EP(Tn-1)-SAR(Tn-1)]
在計算SAR值時,要注意以下幾項原則:
1 .初始值SAR(T0)的確定
若T1周期中SAR(T1)上漲趨勢,則SAR(T0)為T0周期的最低價
若T1周期下跌趨勢,則SAR(T0)為T0周期 的最高價;
2.極點價EP的確定
若Tn周期為上漲趨勢,EP(Tn-1)為Tn-1周期的最高價
若Tn周期為下跌趨勢,EP(Tn-1)為Tn-1周期的最 低價;
3.加速因子AF的確定
(a)加速因子初始值為0.02,即AF(T0)=0.02;
(b)若Tn-1,Tn周期都為上漲趨勢時,
當Tn周期的最高價>Tn-1周期的最高價,則AF(Tn)=AF(Tn-1)+0.02
當Tn周期的最高價<=Tn-1周期的最高價,則AF(Tn)=AF(Tn-1),但加速因子AF最高不超過0.2;
(c)若Tn-1,Tn周期都為下跌趨勢時,
當Tn周期的最低價<Tn-1周期的最低價,則AF(Tn)=AF(Tn-1)+0.02
當Tn周期的最低價>=Tn-1周期的最低價,則AF(Tn)=AF(Tn-1);
(d)任何一次行情的轉變,加速因子AF都必須重新由0.02起算;
比如,Tn-1周期為上漲趨勢,Tn周期為下跌趨勢(或Tn-1下跌,Tn上漲),AF(Tn)需重新由0.02為基礎進 行計算,即AF(Tn)=AF(T0)=0.02;
(e)加速因子AF最高不超過0.2,當AF>0.2時,AF需重新由0.02起算;
4.SAR值的確定
(a)通過公式SAR(Tn)=SAR(Tn-1)+AF(Tn)*[EP(Tn-1)-SAR(Tn-1)],計算出Tn周期的值;
(b)若Tn周期為上漲趨勢,
當SAR(Tn)>Tn周期的最低價(或SAR(Tn)>Tn-1周期的最低價),則Tn周期最終 SAR值應為Tn-1、Tn周期的最低價中的最小值
當SAR(Tn)<=Tn周期的最低價且SAR(Tn)<=Tn-1周期的最低價,則Tn周期最終SAR值為SAR(Tn),即SAR=SAR(Tn);
(c)若Tn周期為下跌趨勢,
當SAR(Tn)<Tn周期的最高價(或SAR(Tn)<Tn-1周期的最高價),則Tn周期最終 SAR值應為Tn-1、Tn周期的最高價中的最大值,
當SAR(Tn)>=Tn周期的最高價且SAR(Tn)>=Tn-1周期的最高價,則Tn周期最終SAR值為SAR(Tn),即 SAR=SAR(Tn);
t——當日;
n——時間長度;
Ci——第i日的[收盤價]
Hi——第i日的最高價;
Li——第i日的[最低價]
TRi = max(Hi,Ci-1)-min(Li,Ci-1)
註:一般取n=14,m=6。
其實就是一個求和取平均的過程。
計算公式如下:
乖離率=[(當日收盤價-N日平均價)/N日平均價]*100%
其中N取:6,12,24
BIAS算是比較簡單的一個指標。
以日CCI計算為例,其計算方法有兩種。
第一種計算過程如下:
CCI(N日)=(TP-MA)÷MD÷0.015
其中,TP=(最高價+最低價+收盤價)÷3
MA=近N日收盤價的累計之和÷N
MD=近N日(MA-收盤價)的累計之和÷N
0.015為計算系數,N為計算周期
網上還有一種計算方式是用平均絕對偏差弄的,直接第一種實現了也就沒有搞第二種了。這概念只能認得幾個字,令人望而卻步。
稍微提示一下,計算MD的時候請用絕對值,不然算出的來的指標線會不對。