cppdcc同人圖與草坪拼音


本站AI自動判斷提供您所需要的app下載:點我下載安裝,你懂的APP

本文將介紹一些在開發多 Linux 平臺 C++ 應用時可能遇到的兼容性問題和相關的解法。雖然是以 C++ 為講述對象,但兼容性這個問題,在沒有 VM 幫你做這些臟活累活的情況下,是所有 C-like 語言(比如 Go、Rust 等)都可能遇到的。

受個人經驗所限,本文所討論內容僅限于 x86 架構下,但相信相關的原理和規則在其他架構下也是相通的,可作借鑒參考。

Linux 二進制兼容

首先,我們來看看什么叫二進制兼容?

眾所周知,不同的 Linux 發行版會攜帶不同的基礎庫版本,以最常用的 g++ 工具鏈為例,基于它們的應用會附帶地依賴上 libc, libgcc, libstdc++ 等庫。顯然,當應用使用了高版本才具備的功能后,編譯得到的二進制內容在低版本環境中運行時,將產生兼容問題,最常見的表現就是無法運行

簡而言之,當所提供的應用 binary 在目標平臺上無法正常運行(包括跑不起來這種最差的情況),我們就認為這是一種不兼容的情況。

多平臺兼容的常用方法

為了讓應用兼容多平臺,從開發者的角度一般有以下三個方法 [1]。

1. 為每個目標平臺提供特定的 Binary

顧名思義,對于每個目標平臺,這種方法都要提供相應的 binary。

這種方法的好處在于每個 binary 或是安裝包都能夠對目標平臺進行針對性適配,在承諾支持的范圍內基本不需要擔心發生不兼容的情況。

但這種方式的缺點也很明顯,維護代價較大。應用每新增一個目標平臺,在發布流程中就要為之構建相應的編譯打包環境,即便是借助一些手段(比如容器鏡像)來實現流程自動化,維護諸多的編譯環境本身也會帶來不小的工作量。

2. 低版本環境編譯

此方法要求開發者將編譯環境設置在目標平臺中版本最低的環境上,此處的版本主要指的編譯工具鏈。比如我們期望提供 CentOS 5.x 到 7.x 都能運行的應用,那么可以將編譯環境設置在 5.0 上。

這個方法源于對 Linux 向后兼容能力的信任,根據經驗,在低版本上編譯得到的 binary,在高版本上有很大概率能夠正常運行。

此方法的缺陷是應用能夠使用的功能受限于編譯環境,包括所能夠使用的語言特性和系統功能。比如:

如果環境上的 gcc 工具鏈仍在 4.1.x 版本,我們顯然無法使用 C++11 等特性。

某些系統庫(比如 journal)需要更高的內核版本支持,那么在低版本環境下將無法使用。

3. 靜態鏈接

嚴格來說,這不算是一個獨立解決多平臺兼容的方法,因為它完全可以結合前兩個方法一并使用,但考慮到這是一個非常常用的辦法,在此我們簡單地說兩句。

此方法解決兼容問題的基本思路是將應用所依賴的各種庫都進行靜態鏈接,這樣在發布應用時僅需要提供一個單獨的 binary,而無需附帶上一系列關聯的動態庫(so 文件),能夠有效地降低不兼容問題出現的概率。

但靜態鏈接并非萬能,拋開體積膨脹以外,它還有這樣兩個問題。一方面,有些庫的 license 中會限制靜態鏈接,另一方面,即使我們可以對大部分庫進行靜態鏈接,但隨系統發布的 libc.so [2] 是無法這樣做的,它也會帶來一些兼容問題 。

我們的多平臺兼容思路

本節將簡要介紹在開發 Logtail(SLS 采集 agent)的過程中,我們和多平臺兼容「斗爭」時做出的一些選擇。

1. 不排斥高版本編譯器(只要穩定)

最初,我們僅采用了方法 2 來做到盡可能地兼容多平臺,效果很好。但隨著 C++ 標準的不斷演進,我們面臨了一個直接問題:低版本環境「落后」的語法支持和日益了解的新特性之間的矛盾。在低版本環境下,由于僅支持 C++98,我們:

沒法在恰當的地方引入 move 語義,只能依靠注釋。

重復地敲打著 auto 就能替換的迭代器類型聲明。

...

但經過調研和實踐后,我們發現,其實只需要借助靜態鏈接標準庫+手動構建編譯工具,就能夠在保證兼容性地情況下,開心地使用新特性。

2. 盡可能地靜態鏈接(注意版權)

雖然靜態鏈接會導致 binary 產生一定程度的體積膨脹,但相比它能夠帶來的兼容能力的提升,這些額外的空間開銷我們認為是值得的。

對于版權,豐富的開源生態并沒有讓我們失望,暫未遇到任何這方面的限制。

3. 符號替換

細數我們所遇到的兼容性問題,大多數都是在運行環境中缺失所需符號或是符號版本不一致導致的,此時符號替換將是一個很好的解決思路,事實上,我們也是借此方法來解決 libc.so 帶來的一些問題。

操作實踐

對于一篇實踐類的文章,單純使用文字來介紹總是匱乏的,也無法清楚地描述實際的問題。因此,本節將通過一個示例來對前述內容進行補充說明。

示例應用代碼

在示例應用中,我們使用了 C++11 的一些特性,包括 uniform initialization, lambda (with capture), for auto 等。

#include <iostream> #include <vector> #include <string> #include <algorithm> using namespace std; int main() { vector<string> vec = {"b", "a", "d"}; auto printVec = [&vec]() { for (auto &s : vec) { std::cout << s << std::endl; } }; for (int i = 0; i < 10; ++i) { vec.push_back(to_string(i)); } std::cout << "===== Before =====" << std::endl; printVec(); sort(vec.begin(), vec.end()); std::cout << "===== After =====" << std::endl; printVec(); return 0; }

編譯及運行環境

如下是示例所使用的兩個環境,我們將在 CentOS 7 上使用 g++ 4.8.5 對應用進行編譯,然后把得到的 binary 放到 CentOS 5 上運行。

# 在兩個環境上分別運行此命令 $ cat /etc/redhat-release; uname -r; g++ --version | grep g++; ld --version | grep ld # 編譯環境(高版本) CentOS Linux release 7.5.1804 (Core) 3.10.0-862.3.2.el7.x86_64 g++ (GCC) 4.8.5 20150623 (Red Hat 4.8.5-28) GNU ld version 2.27-27.base.el7 # 運行環境(低版本) CentOS release 5.7 (Final) 2.6.18-274.el5 g++ (GCC) 4.1.2 20080704 (Red Hat 4.1.2-51) GNU ld version 2.17.50.0.6-14.el5 20061020

原始版本(v1)

執行 g++ -o main_v1 -std=c++11 main.cpp 進行編譯,將得到的結果拷貝到運行環境執行,結果如下:

./main_v1: /usr/lib64/libstdc++.so.6: version `GLIBCXX_3.4.14' not found (required by ./main_v1)

這個報錯表示所鏈接的 libstdc++.so 無法滿足版本要求。對此,分別查看一下 libstdc++.so 和 main_v1 中 GLIBCXX 的版本情況:

$ strings main_v1 | grep "GLIBCXX_" GLIBCXX_3.4.5 GLIBCXX_3.4.14 GLIBCXX_3.4 $ strings /usr/lib64/libstdc++.so.6 | grep "GLIBCXX_" GLIBCXX_3.4 GLIBCXX_3.4.1 ... GLIBCXX_3.4.8 GLIBCXX_FORCE_NEW

可以看到,main_v1 要求 3.4.14 而運行環境上的 libstdc++.so 僅支持到 3.4.8,所以產生了這個錯誤。

對于這個問題,由于運行環境的不可控,我們無法通過更新 libstdc++.so 來解決,只能通過修改自己的應用來進行兼容。

解決辦法:靜態鏈接 libstdc++.a。

此處我們使用 nm 來進一步分析 main_v1 究竟依賴了哪些 3.4.14 版本的符號(配合 c++filt 進行 demangle),結果如下:

$ nm main_v1 | grep "GLIBCXX_3.4.14" U _ZNSsaSEOSs@@GLIBCXX_3.4.14 U _ZNSsC1EOSs@@GLIBCXX_3.4.14 $ c++filt _ZNSsaSEOSs std::basic_string<char, std::char_traits<char>, std::allocator<char> >::operator=(std::basic_string<char, std::char_traits<char>, std::allocator<char> >&&) $ c++filt _ZNSsC1EOSs std::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string(std::basic_string<char, std::char_traits<char>, std::allocator<char> >&&)

可以發現,這是與 string 相關的兩個以右值引用為參數的方法,所以在不支持 C++11 的低版本環境上,libstdc++.so 顯然不可能有這些符號。

靜態鏈接 libstdc++(v2)

一般來說,編譯環境中是不會自帶 libstdc++.a,需要做一些額外的安裝,比如 CentOS 7 可以直接通過 yum 安裝。

如下是做了靜態鏈接后的運行結果:

# 安裝 + 靜態鏈接 $ sudo yum install -y libstdc++-static $ g++ -o main_v2 -static-libstdc++ -std=c++11 main.cpp # 運行 ./main_v2: /lib64/libc.so.6: version `GLIBC_2.14' not found (required by ./main_v2)

和 v1 類似的錯誤,借助同樣的方法可以發現,這次是 libc.so 的版本不支持導致的,main_v2 需要 2.14 而運行環境上僅支持到 2.5。

$ strings main_v2 | grep "GLIBC_" GLIBC_2.3 GLIBC_2.14 GLIBC_2.3.2 GLIBC_2.2.5 $ strings /lib64/libc.so.6 | grep "GLIBC_" GLIBC_2.2.5 GLIBC_2.2.6 GLIBC_2.3 GLIBC_2.3.2 GLIBC_2.3.3 GLIBC_2.3.4 GLIBC_2.4 GLIBC_2.5 GLIBC_PRIVATE

作為一個隨系統釋出的庫,libc.so 帶來的兼容性問題一般無法通過靜態鏈接解決(理論上或許可行),我們只能尋求其他的方法。

符號替換(v3)

為了解決 v2 的問題,我們先用 nm 看看究竟是哪個符號需要 GLIBC 2.14,結果如下:

$ nm main_v2 | grep "GLIBC_2.14" U memcpy@@GLIBC_2.14

可以看到,只有 memcpy 這一個符號,直覺上這個方法的實現不太可能跟著版本在不停更新。在查看 glibc 源碼后可以發現,string/memcpy.c 在 2.2.5 -> 2.14 之間都沒有任何變化。因此,低版本環境上的 libc.so 其實已經提供了我們需要的 memcpy 的實現,唯一需要解決的就是繞過版本的檢查。

對于這一點,可以借助 內聯匯編 + 符號指定 來實現。出于篇幅,此處我們直接給出相應地解決代碼,具體分析工作可以參考舊版glibc兼容旅程 - CSDN博客。

#ifdef v3 extern "C" { #include <string.h> asm(".symver memcpy, "); void* __wrap_memcpy(void* dest, const void* src, size_t n) { return memcpy(dest, src, n); } } #endif

編譯及運行結果:

$ g++ -o main_v3 -static-libstdc++ -Wl,--wrap=memcpy -Dv3 -std=c++11 main.cpp $ ./main_v3: symbol lookup error: ./main_v3: undefined symbol: _ZNSbIwSt11char_traitsIwESaIwEE4_Rep20_S_empty_rep_storageE

還是無法運行......我們來分析一下,顯然,這是一個 C++ mangled 符號,按道理應該在我們靜態鏈接 libstdc++ 時已經解決了,為什么依舊會出現呢?

搜了一番后發現了這樣一個帖子:SERVER-11641 undefined symbol:
_ZNSbIwSt11char_traitsIwESaIwEE4_Rep20_S_empty_rep_storageE - MongoDB。有興趣的同學可以細看一下帖子的內容,就基本能理解這個問題了,這里我簡單地復述一遍。

我們把 main_v3 拷貝到兩個環境中,然后使用 nm 來查看一下這個符號:

$ nm main_v3 | grep "_ZNSbIwSt11char_traitsIwESaIwEE4_Rep20_S_empty_rep_storageE" # 上面的是編譯環境,下面是運行環境 0000000000680cc0 u _ZNSbIwSt11char_traitsIwESaIwEE4_Rep20_S_empty_rep_storageE 0000000000680cc0 ? _ZNSbIwSt11char_traitsIwESaIwEE4_Rep20_S_empty_rep_storageE

可以發現,中間那個字符有所不同,在高版本的編譯環境上,中間的符號是 u,而低版本的運行環境上則是 ?。

從 man nm 中可知,u 表示這個符號是 GNU unique global symbol 類型,這是 GNU 對 ELF 的一個擴展,它會影響到動態鏈接的過程,換句話說,它會影響到 ld 對動態鏈接過程的處理。

因為 ld/nm 等命令也是基礎環境之一,兩個環境上的版本也有不同,低版本的 2.17.50 并沒有支持這個擴展,所以 nm 查看的結果顯示為未知(?),而 ld 在做動態鏈接時會拋棄掉這種未知的符號,所以也就出現了未定義符號的問題。

對于這個問題,和 libc.so 一樣,我們也沒辦法去更新 ld,所以還是只能在編譯環境中解決此問題。解決的思路就是讓 gcc 不要生成這種擴展類型的符號,讓運行環境中的 ld 能夠識別并鏈接它。

不生成 Unique Global Symbol(v4)

對于這個需求,從 gcc mail list 的回復中可以看到,并沒有這樣的編譯選項,唯一可行的途徑是在編譯 gcc 的時候,指定一個
--disable-gnu-unique-object
參數,因此,解決辦法就是重新編譯一個 gcc...

$ wget http://ftp.tsukuba.wide.ad.jp/software/gcc/releases/gcc-4.8.5/gcc-4.8.5.tar.bz2 $ tar -xjvf gcc-4.8.5.tar.bz2 $ cd gcc-4.8.5 && ./contrib/download_prerequisites $ mkdir build-result && cd build-result $ ../configure --enable-checking=release --enable-languages=c,c++ --disable-multilib --disable-gnu-unique-object --prefix=/usr/local/gcc-4.8.5 $ make && sudo make install $ export PATH=/usr/local/gcc-4.8.5:$PATH

唯一需要注意的一點是選擇好安裝的目錄,并且將安裝目錄的內容 export 到 PATH 中。

使用編譯得到的 g++,使用 v3 的編譯命令得到 main_v4 后,在運行環境中成功執行。

最后,我們可以直接 nm 比較一下 v3, v4:

$ nm main_v3 | grep "_ZNSbIwSt11char_traitsIwESaIwEE4_Rep20_S_empty_rep_storageE" 0000000000680cc0 u _ZNSbIwSt11char_traitsIwESaIwEE4_Rep20_S_empty_rep_storageE $ nm main_v4 | grep "_ZNSbIwSt11char_traitsIwESaIwEE4_Rep20_S_empty_rep_storageE" 000000000067dcc0 V _ZNSbIwSt11char_traitsIwESaIwEE4_Rep20_S_empty_rep_storageE

在 v4 中的符號類型發生了變化,V 代表的 weak object,這個類型可以兼容低版本的 ld。

小結

就我個人感受而言,鉆研二進制兼容性更多是個熟悉和理解編譯工具以及操作系統所定義規則的過程,遠不及設計和實現它們時的難度。但考慮到這個探索的過程也算挺折騰的,所以盡量把能夠總結的內容通過本文進行了整理,希望能讓讀者在后續做相關事情時少才踩些坑。

由于側重于介紹方法和分析的思路,文中所使用的應用示例比較簡單(只考慮了工具鏈依賴庫的范疇),后續有時間會補一篇針對較完善應用的兼容性改造過程,敬請期待。

參考

    Creating portable Linux binaries

    此處的 libc.so 來源于 glibc,而非 Linux 歷史上的其他來源,對這段歷史感興趣的同學可以看一下 libc(7)

    舊版glibc兼容旅程 - CSDN博客

    SERVER-11641 undefined symbol: _ZNSbIwSt11char_traitsIwESaIwEE4_Rep20_S_empty_rep_storageE - MongoDB

    Re: --no-gnu-unique option to disable STB_GNU_UNIQUE

另外關于c++ Linux后臺服務器開發的一些知識點分享:Linux,Nginx,MySQL,Redis,P2P,K8S,Docker,TCP/IP,協程,DPDK,webrtc,音視頻等等視頻。

喜歡的朋友可以后臺私信【1】獲取學習視頻

一、會寫的字。

擱(耽擱)(擱置)(擱淺)

填(填補)(填空)(填寫)

怨(怨恨)(埋怨)(怨言)

掀(掀起)(掀開)

唉(唉聲嘆氣)

裹(包裹)(裹腳)

魁(魁梧)(奪魁)

梧(梧桐)(魁梧)

淋(淋浴)(淋濕)(日曬雨淋)

撕(撕開)(撕扯)(撕碎)

霉(倒霉)(發霉)(青霉素)

慮(焦慮)(顧慮)(憂慮)

悠(悠久)(悠長)(悠閑)

儀(禮儀)(儀表)(儀式)

歉(道歉)(歉意)(歉疚)

溜(溜走)(溜冰)(滑溜)

嘿(嘿!)

割(割開)(收割)(割草)

二、辨字組詞。

三、詞語積累。

1.近義詞。

抱怨——埋怨 憂慮——焦慮

嚴肅——嚴厲 沮喪——懊喪

打擾——打攪 羞愧——慚愧

聲望——名望 著迷——入迷

悅耳——動聽 果然——果真

的確——確實 叮囑——囑咐(吩咐)

心驚肉跳——膽戰心驚

自作自受——自食其果

自言自語——喃喃自語

流連忘返——戀戀不舍

忐忑不安——坐立不安

躡手躡腳——輕手輕腳

興高采烈——興致勃勃

無所不知——見多識廣

2.反義詞。

潮濕——干燥 嚴肅——活潑

偶然——必然 沮喪——得意

莊重——輕浮 羞愧——驕傲

慈祥——嚴厲 溫柔——粗暴

耐心——厭煩 熟悉——陌生

悅耳——刺耳

寒風呼嘯——暖風習習

躡手躡腳——大模大樣

流連忘返——歸心似箭

忐忑不安——鎮定自若

興高采烈——無精打采

3.量詞積累。

一(張)帆 一(匹)馬

一(片)樹林 一(件)事情

一(束)陽光 一(把)錘子

4.詞語搭配。

(洶涌澎湃)的海浪 (蒼白僵硬)的手

(清新)的海風 (流連忘返)的地方

(瘦削)的臉 (怒目圓睜)的臉

(茫然)的眼睛 (隆重)的儀式

(慈祥)的眼神 (唯一)的聽眾

(溫柔)的嗓音 (躡手躡腳)地走出家門

(靜靜)地坐著/望著(耐心)地回答

(幸福)地歌唱

5.詞語歸類。

形容心神不安的成語:

忐忑不安 惴惴不安

驚慌失措 六神無主

形容沒有變化的詞語:

一如既往 一如往日

始終如一 自始至終

無~不~式成語:

無所不知 無所不能

無所不在 無所不及

6.成語盤點。

心驚肉跳 忐忑不安

躡手躡腳 流連忘返

一如既往 溜之大吉

一動不動 盡心盡力

無所不知 十指連心

大吃一驚 身無分文

刻苦銘心 興高采烈

自作自受 不由分說

自言自語 洶涌澎湃

四、日積月累。

輕諾必寡信。《老子》

民無信不立。《論語》

不精不誠,不能動人。《莊子》

誠者,天之道也;

誠之者,人之道也。

《禮記》

有所期諾,纖毫必償;

有所期約,時刻不易。

《袁氏世范》

五、佳句欣賞。

1.屋外寒風呼嘯,洶涌澎湃的海浪拍擊著海岸,濺起一陣陣浪花。海上正起著風暴,外面又黑又冷,這間漁家的小屋里卻溫暖而舒適。地掃得干干凈凈,爐子里的火還沒有熄,食具在擱板上閃閃發亮。掛著白色帳子的床上,五個孩子正在海風呼嘯聲中安靜地睡著。(環境描寫)《窮人》

2.桑娜沉思∶丈夫不顧惜身體,冒著寒冷和風暴出去打魚,她自己也從早到晚地干活,還只能勉強填飽肚子。孩子們沒有鞋穿,不論冬夏都光著腳跑來跑去;吃的是黑面包,菜只有魚。不過,感謝上帝,孩子們都還健康。沒什么可抱怨的。(心理描寫)《窮人》

3.漁夫皺起眉,他的臉變得嚴肅、憂慮。“嗯,是個問題!”他搔搔后腦勺說,“嗯,你看怎么辦?得把他們抱來,同死人呆在一起怎么行!哦,我們,我們總能熬過去的!快去!別等他們醒來。”(動作/語言/神態描寫)《窮人》

4.如果沒有他每天早上這寬厚的一笑,我就不會繼續白看他的書,也就不會有那刻骨銘心的兩個耳光。(假設)《別餓壞了那匹馬》

5.林子里靜極了。沙沙的足音,聽起來像一曲悠悠的小令。(比喻/環境描寫)《唯一的聽眾》

6.我感覺到背后有人,轉過身時,嚇了一跳:一位極瘦極瘦的老婦人靜靜地坐在木椅上,平靜地望著我。(神態描寫)《唯一的聽眾》

7.她慈祥的眼神平靜地望著我,像深深的潭水……《唯一的聽眾》

8.后來,拉小提琴成了我無法割舍的愛好,我能熟練地拉許多曲子。在各種文藝晚會上,我有機會面對成百上千的觀眾演奏小提琴曲。那時,我總是不由得想起那位“耳聾”的老人,那清晨里我唯一的聽眾……(點題)《唯一的聽眾》

9.一天,我心愛的金絲雀突然死了。我非常難過,心比被錘子砸了的手指還疼。《用心靈去傾聽》

10.我相信蘇珊的話,我想可愛的小鳥的確到了另一個世界,一個比我們這個世界更為美麗的地方,幸福地歌唱。《用心靈去傾聽》

六、課文主題。

《窮人》這篇文章通過記述漁夫和他的妻子桑娜收養鄰居西蒙的兩個孩子的故事,反映了窮人的悲慘生活和他們在困苦中寧可自己吃苦也要幫助別人的高尚品質。

《別餓壞了那匹馬》敘述了殘疾青年用善意的謊言讓“我”繼續看書的故事,贊揚了殘疾青年不計一切得失、想方設法讓“我”看書的良苦用心,表達了“我”得知真相后的感激之情。

《唯一的聽眾》記述了“我”在一位音樂教授的真誠幫助下,由一個音樂“白癡”成長為能上臺演奏的小提琴手的故事,贊揚了老教授愛護、鼓勵年輕人成才的美德,表達了“我”對德高望重的老教授的敬佩、感激之情。

《用心靈去傾聽》記述了“我”與問訊處的工作人員蘇珊交往的過程,贊美了蘇珊用心靈傾聽孩子的心聲、用愛心幫助孩子的善良品質,表達了“我”對蘇珊的深切的懷念之情。

七、單元鏈接與拓展。

關于自信的名言:

天生我材必有用。——李白

恢弘志士之氣,不宜妄自菲薄。——諸葛亮

有信心的人,可以化渺小為偉大,化平庸為神奇。——蕭伯納

一、給畫線字注音。(4分)

1.他悄悄地走到廚房,輕輕地掀( )起鍋蓋,好像一只偷吃的老鼠。

2.在神圣的教堂里,她一個人跪在神像前不停地抱怨( )生活的不公。

3.不知從何時開始,他對手工藝品開始著( )迷。

4.媽媽躡( )手躡腳地推開了兒子的房門,為他輕輕地蓋好了被子才慢慢地走了出來。

二、看拼音,寫詞語。(8分)

kuí wǔ jiè yì

( ) ( )

quàn zǔ sī pò

( ) ( )

qīng tīng gē bǎn

( ) ( )

máng rán miǎn qiǎng

( ) ( )

三、根據語境,解釋劃線詞語的意思。(8分)

1.偷看書的時候,羞愧不已的我根本不敢回頭去看他那張瘦削的臉。

意思: ________________________

2.一拿到自己掙得的第一筆錢,我泰然地走到精品屋,為媽媽挑選生日禮物。

意思: ________________________

3.通過討論,他們決定由參會人員中最有聲望的人去頒獎典禮。

意思: ________________________

4.屋外寒風呼嘯,洶涌澎湃的海浪拍擊著海岸,濺起一陣陣浪花。

意思: ________________________

四、先連線,再選詞填空。(6分)

心驚 自受

流連 肉跳

十指 忘返

自作 連心

1.驚險的極限挑戰活動令人( ),勇敢的挑戰者卻是鎮定自若。

2.即使孩子不小心磕破了皮,母親都會很心痛,畢竟( )。

五、判斷下列句子采用的描寫方法,把正確的序號填在括號內。(8分)

①環境描寫②語言描寫③心理描寫④動作描寫

1.桑拿沉思:丈夫不顧惜身體,冒著寒冷和風暴出去大魚,她自己也從早到晚地干活,還只能勉強填飽肚子。 ( )

2.說罷,父親奪過我手里的書,匆匆地翻了一下,還給那個年輕人,拽著我走了。 ( )

3.我停下來時,她總不忘說上一句:“真不錯。我的心已經感受到了。謝謝你,小伙子。” ( )

4.村子里靜極了。沙沙的足音,聽起來像一曲悠悠的小令。 ( )

六、把下列名句補充完整或填寫出處。(8分)

1. _________,不能動人。《莊子》

2.有所期諾,_________ ;

_________,_________ 。

《袁氏世范》

3.“民無信不立”出自_________。

4._________,天之道也;

_________, _________ 。

《禮記》

七、口語交際。(5分)

學校即將舉辦一次關于“講誠信與善意的謊言是否相同”的辯論會。有些同學認為“善意的謊言也是一種誠信”,有的同學認為“善意的謊言就是撒謊,是不誠信的表現”,你支持哪一方的觀點呢?請說說你的觀點及理由。

觀點: ______________________

理由: ______________________

八、閱讀天地。(23分)

(一)課內閱讀。(9分)

《唯一的聽眾》節選

一天早晨,我躡手躡腳地走出家門,心里充滿了神圣感,仿佛要去干一件非常偉大的事情。林子里靜極了。沙沙的足音,聽起來像一曲悠悠的小令。我在一棵樹下站好,莊重地架起小提琴,像舉行一個隆重的儀式,拉響了第一支曲子。但我很快又沮喪起來,我覺得自己似乎又把鋸子帶到了樹林里。

我感覺到背后有人,轉過身時,嚇了一跳:一位極瘦極瘦的老婦人靜靜地坐在木椅上,平靜地望著我。我的臉頓時燒起來,心想,這么難聽的聲音一定破壞了這林中的和諧,一定破壞了這位老人正獨享的幽靜。

1.“我躡手躡腳”的原因是什么?(2分)

2.請找出文中的比喻句用“______ ”畫出來,并說說它的好處。(3分)

3.為什么“我”看到有個老人靜靜地坐在木椅上望著我,頓時感到臉燒?(4分)

(二)課外閱讀。(14分)

父親的愛

①爹不懂得怎樣表達愛,使我們一家人融洽相處的是我媽。他只是每天上班下班,而媽則把我們做過的錯事開列清單,然后由他來責罵我們。

②有次我偷了塊糖果,他要我把它他回去,告訴賣糖的說是我偷的,說我愿意替他拆箱卸貨作為賠償。但媽媽卻明白我只是個孩子。

③我在運動場打秋千跌斷了腿,在前往醫院途中一直抱著我的,是我媽。爹把汽車停在急癥室門口,他們叫他駛開,說那空位置是留給緊急車輛停放的。爹聽了便叫嚷道:“你以為這是什么車?旅游車?”

④在我的生日會上,爹總是顯得有點不太相稱。他只是忙于吹氣球,布置餐桌,做雜務。把插著蠟燭的蛋糕推過來讓我吹的是我媽。

⑤我翻閱照相冊時,人們總是問:“你爸爸是什么樣子的?”天曉得!他老是忙著替別人拍照,媽和我笑容可掬地一起拍的照片,多得不可勝數。

⑥我記得媽媽有一次叫他教我騎自行車。我叫他別放手,但他卻說是應該放手的時候了,我摔到這后,媽跑過來扶我,爸卻揮手要她走開。我當時生氣極了,決心要給他點顏色看。于是我馬上再爬上自行車,而且自己騎給他看,他只是微笑。

⑦我念大學時,所有的家信都是媽寫的。他除了寄予支票以外,還寄過一封短柬給我,說因為我沒有在草坪上踢足球了,所以他的草坪長得很美。

⑧每次我打電話回家,他似乎都想跟我說話,但結果總是說:“我叫你媽來聽。”

⑨我結婚時,掉眼淚的是我媽。他只是大聲擤了一下鼻子,便走出房間。

⑩我從小到大都聽他說:“你到哪里去了?什么時候回家?汽車有沒有汽油?不,不準去。”爹不知道怎樣表達我。除非……

1.哪一句話是本文的中心句?用原文回答。(2分)

2.用簡短的話概括本文的主要內容?(3分)

3.請寫出第六段最后一句話中“微笑”的含義。(4分)

4.文章最后一段的作用是什么?(5分)

九、作文。(30分)

“愛”是人生永恒的主題,生活中,有關愛你的家人,有你關愛的小動物,也有陌生人對你的幫助以及你對陌生人的幫助。我們并不缺少愛,而是缺少真正地體會愛。回憶一下,在你的周圍有沒有發生哪些讓你記憶深刻的事情能夠體現“愛”。以“關愛”為話題,寫一篇作文,題目自擬。

要求:寫清事情的發展過程;注意人物的語言、動作、心理活動等;不少于450字。

參考答案

一、xiān yuàn zháo niè

二、魁梧 介意 勸阻 撕破 傾聽 擱板 茫然 勉強

三、1.形容身體或臉很瘦。

2.形容心情十分安定。

3.為眾人所仰望的名聲。

4.文中形容海風發出高而長的聲音,說明寒風猛烈。

五、③④②①

六、不精不誠

纖毫必償 有所期約,時刻不易

《論語》

誠者 誠之者,人之道也。

七、我贊成善意的謊言也是一種誠信。

謊言是善意的,說明是為了保護一些人不讓他們受到傷害,所以這種做法是值得肯定。因此肯定的做法是值得提倡的,所以我認為“善意的謊言也是一種誠信。”

八、(一)

1.“我”害怕驚動家人,發現自己去練琴。

2.沙沙的腳步聲,聽起來像一曲悠悠的小令。好處:“沙沙的足音”比喻成了“一曲悠悠的小令”,形象地說明“我”對拉好琴重新找回了自信。

3.因為“我”的琴技不好,不希望有人聽見自己拉琴,卻被老人聽見了,讓“我”再次失去了自信。

(二)

1.爹不懂得怎樣表達愛,使我們一家人融洽相處的是我媽。

2.通過列舉了各種種種事實,來表達父親對“我”的愛。

3.父親對“我”學會了自行車感到高興的笑;為我面對失敗,能夠有再次嘗試的勇氣而感到驕傲的笑。

4.用疑問的方式總結全文,概括中心,告訴讀者父親不同方式來表達對“我”的愛。

九、作文(略)。