從8月15號來到北京一直到今天,一月有余。來的這段時間一直准備筆試面試,大大小小的公司,亂七八糟面了10多家,近期才安頓下來。面試的這段時間感覺自己成長了不少。初來到這個陌生的城市一臉茫然,不會乘地鐵、不會有擠公交、不會恰如其分的生活。。。
面試是進入職場的第一道坎,因為我本身學校太一般的問題在面試中遇到了各種不爽,和那些高學歷的相比自己真是信心大跌。我面試的方向是php開發工程師,主要做網站後台、APP接口等。我所面試的公司、試題、心得都在我的個人網站上,感興趣的可以看看:http://dwz.cn/1KMpea。下面是我這段時間總結的面試方面的常考常問的知識點,希望對大家有所幫助,不對之處歡迎指出。
總結:
php部分我是按照面試常問的問題總結的,下面的問題在面試中出場率很高。問題比較基礎
--------------------PHP部分---------------------
PHP中幾個輸出函數echo,print(),print_r(),sprintf(),var_dump()的區別1:echo:是語句不是函數,沒有返回值,可輸出多個變量值,不需要圓括號。不能輸出數組和對象,只能打印簡單類型(如int,string)。
2:print:是語句不是函數,有返回值 1 ,只能輸出一個變量,不需要圓括號。不能輸出數組和對象,只能打印簡單類型(如int,string)。
3:print_r:是函數,可以打印復合類型,例如:stirng、int、float、array、object等,
輸出array時會用結構表示,而且可以通過print_r($str,true)來使print_r不輸出而返回print_r處理後的值
4:printf:是函數,把文字格式化以後輸出(參看C語言)
5:sprintf:是函數,跟printf相似,但不打印,而是返回格式化後的文字(該函數把格式化的字符串寫寫入一個變量中,而不是輸出來),其 他的與printf一樣。
例如: $str = "Hello"; $number = 123;
$txt = sprintf("%s world. Day number %u",$str,$number); //輸出: Hello world. Day number 123
6:var_dump():函數,輸出變量的內容、類型或字符串的內容、類型、長度。常用來調試。
寫個函數來解決多線程同時讀寫一個文件的問題。
1 <?php 2 $fp = fopen("/tmp/lock.txt","w+"); 3 if(flock($fp, LOCK_EX)){// 進行排它型鎖定 4 fwrite($fp,"Write something here\n"); 5 flock($fp, LOCK_UN);// 釋放鎖定 6 }else{ 7 echo "Couldn't lock the file !"; 8 } 9 fclose($fp); 10 ?>
禁掉cookie的session使用方案,設置session過期的方法,對應函數:
通過 url 傳值,把session id附加到url上(缺點:整個站點中不能有純靜態頁面,因為純靜態頁面session id 將無法繼續傳到下一頁面) 通過隱藏表單,把session id 放到表單的隱藏文本框中同表單一塊提交過去(缺點:不適用<a>標簽這種直接跳轉的非表單的情況) 直接配置php.ini文件,將php.ini文件裡的session.use_trans_sid= 0設為1,(好像在win上不支持) 用文件、數據庫等形式保存Session ID,在跨頁過程中手動調用1 第一種 setcookie() 直接用setcookie設置session id的生命周期。 2 3 $lifetime=60; //保存1分鐘 4 session_start(); 5 setcookie(session_name(), session_id(), time()+$lifetime, "/"); 6 第二種 session_set_cookie_params() 7 $lifetime=60;//保存1分鐘 8 session_set_cookie_params($lifetime); 9 session_start(); 10 session_regenerate_id(true); 11 其中session_regenerate_id();方法用於改變當前session_id的值,並保留session中數組的值。參數默認為 false,如果設置為true則改變session_id的值,並清空當前session數組。
json格式數據有哪些特點
JSON 一種輕量級的數據交換格式。它基於ECMAScript的一個子集。 JSON采用完全獨立於語言的文本格式,但是也使用了類似於C語言家族的習慣(包括C、C++、C#、Java、JavaScript、Perl、 Python等)。這些特性使JSON成為理想的數據交換語言。 易於人閱讀和編寫,同時也易於機器解析和生成(網絡傳輸速率)。
JSON的結構基於下面兩點
1. "名稱/值"對的集合 不同語言中,它被理解為對象(object),記錄(record),結構(struct),字典(dictionary),哈希表(hash table),鍵列表(keyed list)等PHP 如何獲取客戶端的IP地址,
用$_SERVER獲取的IP地址有什麼問題?
$_SERVER['REMOTE_ADDR'] ; 通過全局數組來獲得
getenv('REMOTE_ADDR') ; 通過環境變量來獲得
當客戶機使用代理的時候獲取不到真實的IP地址
寫一個函數,可以遍歷文件夾下的所有文件和文件夾。
1 function get_dir_info($path){ 2 $handle = opendir($path);//打開目錄返回句柄 3 while(($content = readdir($handle))!== false){ 4 $new_dir = $path . DIRECTORY_SEPARATOR . $content; 5 if($content == '..' || $content == '.'){ 6 continue; 7 } 8 if(is_dir($new_dir)){ 9 echo "<br>目錄:".$new_dir . '<br>'; 10 get_dir_info($new_dir); 11 }else{ 12 echo "文件:".$path.':'.$content .'<br>'; 13 } 14 } 15 } 16 get_dir_info($dir);
有mail.log的一個文檔,內容為若干郵件地址,用’\n’分隔換行。挑選sina.com的地址(包括從文件讀取、過濾到列印出來)。
思路1:用正則表達式(比較慢,效率地,不推薦用)
思路2:cat mail.log | grep sina.com
PHP緩存技術有哪些? tp是局部還是完全緩存?
1. 全頁面靜態化緩存,也就是將頁面全部生成html靜態頁面,用戶訪問時直接訪問的靜態頁面,而不會去走php服務器解析的流程
一群猴子排成一圈,按1,2,…,n依次編號。然後從第1只開始數,數到第m只,把它踢出圈,從它後面再開始數,再數到第m只,在把它踢出去…,如此不停 的進行下去,直到最後只剩下一只猴子為止,那只猴子就叫做大王。要求編程模擬此過程,輸入m、n, 輸出最後那個大王的編號。
1 <?php 2 function fuhuan($allnum, $ti){ 3 $arr = array(); 4 for($i = 0; $i < $allnum; $i++){ 5 $arr[$i] = $i; 6 } 7 8 $nums = 1; 9 while(count($arr) > 1){ 10 foreach ($arr as $key => $value) { 11 if($nums == $ti){ 12 unset($arr[$key]); 13 $nums = 1; 14 }else{ 15 $nums++; 16 } 17 } 18 } 19 $new_arr = array_values($arr); 20 var_dump($new_arr[0] + 1); 21 } 22 fuhuan(10,10);
isset() 、empty()與is_null的區別
1、當變量未定義時,is_null()和“參數本身”是不允許作為參數判斷的,會報Notice警告錯誤;
2、empty,isset首先都會檢查變量是否存在,然後對變量值進行檢測。而is_null 和 “參數本身”只是直接檢查變量值,是否為null,因此如果變量未定義就會出現錯誤!
3、isset():僅當null和未定義,返回false;
4、empty():""、0、"0"、NULL、FALSE、array(),未定義,均返回false;
5、is_null():僅判斷是否為null,未定義 報警告;
6、變量本身作為參數,與empty()一致,但接受未定義變量時,報警告;
求兩個文件的相對路徑
1 getpath('/a/b/c/d/e.php', '/a/d/12/34/c.php'); 2 3 function getpath($a, $b){ 4 $aarr = explode('/', $a); 5 $barr = explode('/', $b); 6 $count = count($barr) - 2; 7 $pathinfo = ''; 8 for($i = 1; $i <= $count; $i++){ 9 if($aarr[$i] == $barr[$i]){ 10 $pathinfo .= '../'; 11 }else{ 12 $pathinfo .= $barr[$i] . '/'; 13 } 14 } 15 echo $pathinfo; 16 }
MVC的優缺點 1、 MVC的優點
問題:程序需要定制;每次請求都進行數據庫讀寫開銷不小,另外數據庫是一個單點,可以做數據庫的hash來解 決這個問題。
2:使用 memcached來保存session, 這種方式跟數據庫類似,內存存取性能比數據庫好很多。
問題:程序需要定制,增加 了工作量;存入memcached中的數據都需要序列化,效率較低,斷電或者重啟電腦容易丟失數據;
3: 通過加密的cookie,在A服務器上登錄,在用戶的浏覽器上添加加密的cookie,當用戶訪問B服務器時,檢查有無Session,如果沒有,就檢驗 Cookie是否有效,Cookie有效的話就在B服務器上重建session。簡單,高效, 服務器的壓力減小了,因為session數據不存在服務器磁盤上。根本就不會出現session讀取不到的問題。
問題:網絡請求占用很多。每次請求時,客戶端都要通過cookie發送session數據給服務器,session中數據不能太多,浏覽器對cookie 的大
小存在限制。不適合高訪問量的情況,因為高訪問量的情況下。
正則表達式
匹配中文字符的正則表達式: [\u4e00-\u9fa5]
匹配雙字節字符(包括漢字在內):[^\x00-\xff]
匹配空行的正則表達式:\n[\s| ]*\r
匹配HTML標記的正則表達式:/<(.*)>.*<\/\1>|<(.*) \/>/
匹配首尾空格的正則表達式:(^\s*)|(\s*$)
匹配Email地址的正則表達式:\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*
匹配網址URL的正則表達式:^[a-zA-z]+://(\\w+(-\\w+)*)(\\.(\\w+(-\\w+)*))*(\\?\\S*)?$
匹配帳號是否合法(字母開頭,允許5-16字節,允許字母數字下劃線):^[a-zA-Z][a-zA-Z0-9_]{4,15}$
匹配國內電話號碼:(\d{3}-|\d{4}-)?(\d{8}|\d{7})?
匹配騰訊QQ號:^[1-9]*[1-9][0-9]*$
--------------------linux部分---------------------
core文件是什麼,有什麼用?
core是unix系統的內核。當你的程序出現內存越界的時候,操作系統會中止你的進程,並將當前內存狀態倒出到core文件中,以便進一步分析。程序員可以通過core文件來找出問題所在。它記錄了程序掛掉時詳細的狀態描述。
什麼是core dump Core的意思是內存, Dump的意思是扔出來, 堆出來。開發和使用Unix程序時, 有時程序莫名其妙的down了, 卻沒有任何的提示(有時候會提示core dumped). 這時候可以查看一下有沒有形如core.進程號的文件生成, 這個文件便是操作系統把程序down掉時的內存內容扔出來生成的,它可以做為調試程序的參考. core dump又叫核心轉儲, 當程序運行過程中發生異常, 程序異常退出時, 由操作系統把程序當前的內存狀況存儲在一個core文件中, 叫core dump。如何使用core文件 gdb -c core文件路徑 [應用程序的路徑],進去後輸入where回車, 就可以顯示程序在哪一行當掉的, 在哪個函數中.
為什麼沒有core文件生成呢? core文件的生成跟你當前系統的環境設置有關系, 可以用下面的語句設置一下, 然後再運行程序便成生成core文件.
ulimit -c unlimited core文件生成的位置一般於運行程序的路徑相同, 文件名一般為core.進程號
不用core文件,程序出了問題產生信號是否知道?答:內核向進程發信號嘛。
共享內存除了文件映射還有什麼方式?
共享內存對象映射。
二者有什麼區別:
答:內存映射文件是由一個文件到一塊內存的映射,使應用程序可以通過內存指針對磁盤上的文件進行訪問,其過程就如同對加載了文件的內存的訪問,因此內存文件映射非常適合於用來管理大文件。
請解釋下列10個shell命令的用途
cat:把一個或多個文件內容顯示到標准輸出
chmod:改變文件屬性
chgrp:改變用戶分組
grep:在文件內進行搜索
wc:命令的功能為統計指定文件中的字節數、字數、行數, 並將統計結果顯示輸出。
Linux文件屬性有哪些?(共十位)
-rw-r--r--那個是權限符號,總共是- --- --- ---這幾個位。
第一個短橫處是文件類型識別符:-表示普通文件;c表示字符設備(character);b表示塊設備(block);d表示目錄 (directory);l表示鏈接文件(link);後面第一個三個連續的短橫是用戶權限位(User),第二個三個連續短橫是組權限位 (Group),第三個三個連續短橫是其他權限位(Other)。每個權限位有三個權限,r(讀權限),w(寫權限),x(執行權限)。如果每個權限位都 有權限存在,那麼滿權限的情況就是:-rwxrwxrwx;權限為空的情況就是- --- --- ---。
權限的設定可以用chmod命令,其格式位:chmod ugoa+/-/=rwx filename/directory。例如:
一個文件aaa具有完全空的權限- --- --- ---。
chmod u+rw aaa(給用戶權限位設置讀寫權限,其權限表示為:- rw- --- ---)
chmod g+r aaa(給組設置權限為可讀,其權限表示為:- --- r-- ---)
chmod ugo+rw aaa(給用戶,組,其它用戶或組設置權限為讀寫,權限表示為:- rw- rw- rw-)
如果aaa具有滿權限- rwx rwx rwx。
chmod u-x aaa(去掉用戶可執行權限,權限表示為:- rw- rwx rwx)
如果要給aaa賦予制定權限- rwx r-x r-x,命令為:
chmod u=rwx,go=rx aaa
--------------------服務器部分--------------------- Apache與Nginx的優缺點比較
cgi在2000年或更早的時候用得比較多, 以前web服務器一般只處理靜態的請求,web服務器會根據這次請求的內容,然後會fork一個新進程來運行外部c程序 (或perl腳本...), 這個進程會把處理完的數據返回給web服務器,最後web服務器把內容發送給用戶,剛才fork的進程也隨之退出。 如果下次用戶還請求改動態腳本,那麼web服務器又再次fork一個新進程,周而復始的進行。
後來出現了一種更高級的方式是, web服務器可以內置perl解釋器或php解釋器。 也就是說這些解釋器做成模塊的方式,web服務器會在啟動的時候就啟動這些解釋器。 當有新的動態請求進來時,web服務器就是自己解析這些perl或php腳本,省得重新fork一個進程,效率提高了。
fastcgi的方式是,web服務器收到一個請求時,他不會重新fork一個進程(因為這個進程在web服務器啟動時就開啟了,而且不會退 出),web服務器直接把內容傳遞給這個進程(進程間通信,但fastcgi使用了別的方式,tcp方式通信),這個進程收到請求後進行處理,把結果返回 給web服務器,最後自己接著等待下一個請求的到來,而不是退出。
fastcgi跟cgi的區別是:
在web服務器方面 在對數據進行處理的進程方面
cgi fork一個新的進程進行處理 讀取參數,處理數據,然後就結束生命期
fastcgi 用tcp方式跟遠程機子上的進程或本地進程建立連接 要開啟tcp端口,進入循環,等待數據的到來,處理數據
舉個例子: 服務端現在有個10萬個字單詞, 客戶每次會發來一個字符串,問以這個字符串為前綴的單詞有多少個。 那麼可以寫一個程序,這個程序會建一棵trie樹,然後每次用戶請求過來時可以直接到這個trie去查找。 但是如果以cgi的方式的話,這次請求結束後這課trie也就沒了,等下次再啟動該進程時,又要新建一棵trie樹,這樣的效率就太低下了。 而用fastcgi的方式的話,這課trie樹在進程啟動時建立,以後就可以直接在trie樹上查詢指定的前綴了。
select, poll和epoll的區別 select
select最早於1983年出現在4.2BSD中,它通過一個select()系統調用來監視多個文件描述符的數組,當select()返回後,該數組中就緒的文件描述符便會被內核修改標志位,使得進程可以獲得這些文件描述符從而進行後續的讀寫操作。
select目前幾乎在所有的平台上支持,其良好跨平台支持也是它的一個優點,事實上從現在看來,這也是它所剩不多的優點之一。
select的一個缺點在於單個進程能夠監視的文件描述符的數量存在最大限制,在Linux上一般為1024,不過可以通過修改宏定義甚至重新編譯內核的方式提升這一限制。
另外,select()所維護的存儲大量文件描述符的數據結構,隨著文件描述符數量的增大,其復制的開銷也線性增長。同時,由於網絡響應時間的延遲 使得大量TCP連接處於非活躍狀態,但調用select()會對所有socket進行一次線性掃描,所以這也浪費了一定的開銷。
poll在1986年誕生於System V Release 3,它和select在本質上沒有多大差別,但是poll沒有最大文件描述符數量的限制。
poll和select同樣存在一個缺點就是,包含大量文件描述符的數組被整體復制於用戶態和內核的地址空間之間,而不論這些文件描述符是否就緒,它的開銷隨著文件描述符數量的增加而線性增大。
另外,select()和poll()將就緒的文件描述符告訴進程後,如果進程沒有對其進行IO操作,那麼下次調用select()和poll() 的時候將再次報告這些文件描述符,所以它們一般不會丟失就緒的消息,這種方式稱為水平觸發(Level Triggered)。
直到Linux2.6才出現了由內核直接支持的實現方法,那就是epoll,它幾乎具備了之前所說的一切優點,被公認為Linux2.6下性能最好的多路I/O就緒通知方法。
epoll可以同時支持水平觸發和邊緣觸發(Edge Triggered,只告訴進程哪些文件描述符剛剛變為就緒狀態,它只說一遍,如果我們沒有采取行動,那麼它將不會再次告知,這種方式稱為邊緣觸發),理論上邊緣觸發的性能要更高一些,但是代碼實現相當復雜。
epoll同樣只告知那些就緒的文件描述符,而且當我們調用epoll_wait()獲得就緒文件描述符時,返回的不是實際的描述符,而是一個代表 就緒描述符數量的值,你只需要去epoll指定的一個數組中依次取得相應數量的文件描述符即可,這裡也使用了內存映射(mmap)技術,這樣便徹底省掉了 這些文件描述符在系統調用時復制的開銷。
另一個本質的改進在於epoll采用基於事件的就緒通知方式。在select/poll中,進程只有在調用一定的方法後,內核才對所有監視的文件描 述符進行掃描,而epoll事先通過epoll_ctl()來注冊一個文件描述符,一旦基於某個文件描述符就緒時,內核會采用類似callback的回調 機制,迅速激活這個文件描述符,當進程調用epoll_wait()時便得到通知。
Memcache和Redis區別