├── .gitignore ├── CJKpunct.sty ├── README.md ├── appendix ├── appA.tex └── bibliography.tex ├── body ├── Ch1.tex ├── Ch10.tex ├── Ch2.tex ├── Ch3.tex ├── Ch4.log ├── Ch4.tex ├── Ch5.tex ├── Ch6.log ├── Ch6.tex ├── Ch7.tex ├── Ch8.tex ├── Ch9.tex ├── Copyright.tex ├── Preface.tex └── iconv.sh ├── chinesebst.bst ├── chinesebst_GBK_xelatex.bst ├── figures ├── ch4.jpg ├── ch5.jpg ├── golfer.eps ├── golfer.pdf ├── hit_logo.eps ├── hit_logo.pdf ├── lspcover1.jpg ├── paipai.png ├── title.JPG ├── title_l.jpg └── title_r.jpg ├── fixbbl.txt ├── floatflt.sty ├── gb_452.cap ├── gb_452.cpx ├── gb_452_GBK_xelatex.cap ├── gb_452_GBK_xelatex.cpx ├── gb_452_UTF8.cpx ├── listings.sty ├── lstdoc.sty ├── lstlang1.sty ├── lstlang2.sty ├── lstlang3.sty ├── lstmisc.sty ├── main.bbl ├── main.blg ├── main.tex ├── makefile ├── preface └── cover.tex ├── reference └── reference.bib ├── setup ├── Definition.tex ├── auto │ ├── Definition.el │ └── package.el ├── figtab.tex ├── format.tex ├── package.tex └── type.tex ├── xeCJK.chr └── xeCJK.sty /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | main.log 3 | *.*~ 4 | *.swp 5 | -------------------------------------------------------------------------------- /CJKpunct.sty: -------------------------------------------------------------------------------- 1 | %& -no-cctspace 2 | % 3 | % $Id: CJKpunct.sty,v 1.5 2005/10/18 00:56:34 zlb Exp $ 4 | % 5 | % This is the file CJKpunct.sty for the CJK package 6 | % 7 | % Authors: 8 | % Linbo Zhang (zlb@lsec.cc.ac.cn) 9 | % Wenchang Sun (sunwch@hotmail.com) 10 | % 11 | \def\fileversion{4.6.0} 12 | \def\filedate{2005/10/18} 13 | % 14 | % Changelog: 15 | % 16 | % . 2005/10/18 17 | % 18 | % new method to obtain base name of the current font (mytex) 19 | % 20 | % . 2005/10/14 21 | % 22 | % \ifx\TTFslant\relax ==> \ifx\TTFslant\undefined (mytex) 23 | % 24 | % . 2005/10/11 25 | % 26 | % use \CJK@plane{25} instead of \CJK@plane{01} (zlb) 27 | % 28 | % . 2005/08/28 29 | % 30 | % Redefine \allowbreak 31 | % 32 | % . 2004/02/20 33 | % 34 | % Add macros \CJK@charUL@group, \CJK@punctUL@group to work with 35 | % packages {ulem}{CJKulem}{CJKfntef} 36 | % 37 | % Remove \CJK@testLastpunctb. 38 | % 39 | % . 2004/02/13 40 | % Comment out '\makeatletter' and '\makeatother' (ZLB) 41 | % 42 | % Pretty(?)-reformat the source (ZLB) 43 | % 44 | % . 2004/02/12 45 | % Comment out redefinition of \verbatim - it's incompatible with 46 | % some documentclasses (e.g., ltxdoc) (ZLB) 47 | % 48 | % Define the macro \CJK@read@cfg@done to avoid reading XXXkern.cfg 49 | % multiple times. (ZLB) 50 | % 51 | % . 2004/02/11 52 | % Store globally tokens from the file, say, gbksong.tbl, in the macro 53 | % \CJKpunct/gbksong.tbl, to avoid reloading the same file. (ZLB) 54 | % 55 | % \CJKpunctrule: surround '... \get@external@font ...' in a group to 56 | % avoid unexpected interference. (ZLB) 57 | % 58 | % . 2004/02/10 59 | % Get the external font name through \get@external@font instead of 60 | % using a fixed naming scheme. (ZLB) 61 | % 62 | \ProvidesPackage{CJKpunct}[\filedate\space\fileversion] 63 | 64 | \endlinechar \m@ne 65 | 66 | \newif\ifCJK@punctglue\global\CJK@punctgluefalse 67 | \newif\ifCJK@lastispunct\global\CJK@lastispunctfalse 68 | 69 | \@ifundefined{CJK@nobreakglue} 70 | {\global\def\CJK@nobreakglue{\nobreak\CJKglue\nobreak}}{} 71 | 72 | \@ifundefined{UL@hskip}{\let\UL@hskip\relax}{} 73 | 74 | 75 | \def\CJK@charUL@group{ 76 | \ifx\hskip\UL@hskip 77 | \egroup 78 | \UL@stop 79 | \LA@hskip 0pt 80 | \UL@start 81 | \bgroup 82 | \fi} 83 | 84 | 85 | 86 | \def\CJK@punctUL@group{ 87 | \ifx\hskip\UL@hskip 88 | \egroup 89 | \UL@stop 90 | \UL@start 91 | \bgroup 92 | \fi} 93 | 94 | 95 | \def\CJK@testLastpunct{ 96 | \global\CJK@false 97 | \ifCJK@lastispunct 98 | \ifnum\lastkern = \tw@ 99 | \global\CJK@true 100 | \else 101 | \ifnum\lastkern = \@ne 102 | \global\CJK@true 103 | \fi 104 | \fi 105 | \fi} 106 | 107 | 108 | 109 | %\def\CJK@testLastpunctb{ 110 | % \global\CJK@false 111 | % \ifCJK@lastispunct 112 | % \ifnum\lastkern = \@ne 113 | % \global\CJK@true 114 | % \fi 115 | % \fi} 116 | 117 | \def\@CJK@kern#1#2#3#4 #5 { 118 | \CJK@numbToHex{\CJKtempstra}{`#1} 119 | \CJK@numbToHex{\CJKtempstrb}{`#3} 120 | \global\expandafter\def\csname 121 | @CJK@kern\CJKtempstra\number `#2\CJKtempstrb\number `#4\endcsname{ 122 | \unkern 123 | \unkern 124 | \ifx\hskip\UL@hskip 125 | \LA@hskip -\CJK@punct@postglue 126 | \else 127 | \unskip 128 | \fi 129 | \ifdim #5em=\z@ \else \kern #5em \fi 130 | \nobreak 131 | } 132 | } 133 | \let\GBKkern\@CJK@kern 134 | 135 | \gdef\@CJK@lastpunct{} 136 | 137 | \def\@CJK@punct#1#2 #3 #4 #5 #6 #7 #8 { 138 | % glue and nobreak flag before a punct char 139 | \CJK@numbToHex{\CJKtempstra}{`#1} 140 | \@CJK@prepunct#1#2#3 #5 % 141 | % glue and nobreak flag after a punct char 142 | \@CJK@postpunct#1#2#6 #8 % 143 | % zero-height rule added before a punct char 144 | 145 | \ifdim #4\p@ = \z@ 146 | \global\expandafter\let\csname 147 | @CJK@prerule\CJKtempstra\number`#2\endcsname=\relax 148 | \else 149 | \global\expandafter\def\csname @CJK@prerule\CJKtempstra\number`#2\endcsname{ 150 | \vrule width #4em depth \z@ height \z@ 151 | } 152 | \fi 153 | 154 | % zero-height rule added after a punct char 155 | \ifdim #7\p@ = \z@ 156 | \global\expandafter\let\csname 157 | @CJK@postrule\CJKtempstra\number`#2\endcsname=\relax 158 | \else 159 | \global\expandafter\def\csname 160 | @CJK@postrule\CJKtempstra\number`#2\endcsname{ 161 | \vrule width #7em depth \z@ height \z@ 162 | } 163 | \fi 164 | } 165 | 166 | \def\@CJK@prepunct#1#2#3 #4,#5,#6,#7 { 167 | \CJK@numbToHex{\CJKtempstra}{`#1} 168 | \ifnum #3#4=\z@% 169 | \global\expandafter\def\csname @CJK@preglue\CJKtempstra\number`#2\endcsname{ 170 | \CJK@testLastpunct 171 | \ifCJK@ 172 | \ifCJK@punctglue 173 | \global\CJK@punctgluefalse 174 | \unkern\unkern 175 | \@tempskipa=\lastskip 176 | \unskip 177 | \unpenalty 178 | \hskip\@tempskipa 179 | \fi 180 | \else 181 | \nobreak 182 | \fi 183 | } 184 | \else 185 | \global\expandafter\def\csname @CJK@preglue\CJKtempstra\number`#2\endcsname{ 186 | \CJK@testLastpunct 187 | \ifCJK@ 188 | \ifCJK@punctglue 189 | \global\CJK@punctgluefalse 190 | \unkern\unkern 191 | \@tempskipa=\lastskip 192 | \unskip 193 | \unpenalty 194 | \hskip\@tempskipa 195 | \fi 196 | \else 197 | \nobreak 198 | \fi 199 | \if #41 200 | \hskip #5em plus #6em minus #7em\relax 201 | \fi 202 | \if #31\nobreak \fi 203 | } 204 | \fi 205 | } 206 | 207 | \def\@CJK@postpunct#1#2#3 #4,#5,#6,#7 {% 208 | \CJK@numbToHex{\CJKtempstra}{`#1} 209 | \ifnum #3#4=\z@ 210 | \global\expandafter\let\csname 211 | @CJK@postglue\CJKtempstra\number`#2\endcsname=\relax 212 | \else 213 | \global\expandafter\def\csname 214 | @CJK@postglue\CJKtempstra\number`#2\endcsname{ 215 | \if #31\nobreak 216 | \global\CJK@punctgluefalse 217 | \CJK@kern 218 | \fi 219 | % Note: we insert the glue here otherwise it might be lost 220 | % if the next char is not a Chinese char. 221 | % 222 | % We also insert a penalty to prevent line break, a negative penalty 223 | % might be added by the next Chinese char to allow line break between 224 | % them. 225 | \if #41 226 | \global\CJK@punctgluetrue 227 | \penalty \@M % prevent line break between Chinese-ASCII (e.g., '??,') 228 | \hskip #5em plus #6em minus #7em% 229 | \gdef\CJK@punct@postglue{#5em} 230 | \CJK@CJK 231 | \fi% 232 | } 233 | \fi 234 | } 235 | 236 | \@ifundefined{CJK@direction}{\gdef\CJK@direction{}}{} 237 | \@ifundefined{CJKpunctsymbol}{\global\let\CJKpunctsymbol\CJKsymbol}{} 238 | 239 | \global\let\GBKpunct\@CJK@punct 240 | 241 | % 242 | % Redefine the environment CJK to 243 | % Read CJK punctuation rule when CJK font family is set/changed. 244 | \renewenvironment{CJK}[3][] 245 | {\CJKspace\CJK@envStart{#1}{#2}{#3}\CJK@read@cfg} 246 | {\CJK@envEnd} 247 | 248 | \renewenvironment{CJK*}[3][] 249 | {\CJKnospace\CJK@envStart{#1}{#2}{#3}\CJK@read@cfg} 250 | {\CJK@envEnd} 251 | 252 | % Extract the base name part from the string, say, `gbksong25 at ...' 253 | %\def\CJKpunct@get@tbl#125 at#2\end{\expandafter\global\expandafter\def\csname 254 | % \CJK@enc/\CJK@family/\CJK@series/\CJK@shape.tbl\endcsname{#1}} 255 | %Wenchang SUN 20051014 256 | \def\CJK@empty#1{ 257 | \@tempdimb \f@size\p@ 258 | \ifx\optional@arg \@empty 259 | \else 260 | \expandafter\ifx 261 | \csname CJK@\mandatory@arg/\f@size/\the\@tempdimb\endcsname \relax 262 | \@tempdimb \optional@arg\@tempdimb 263 | #1{Font\space shape\space `\curr@fontshape'\space 264 | will\space be\MessageBreak 265 | scaled\space to\space size\space \the\@tempdimb} 266 | \expandafter 267 | \gdef\csname CJK@\mandatory@arg/\f@size/\the\@tempdimb\endcsname{} 268 | \fi 269 | \fi 270 | \edef\external@font{ 271 | \mandatory@arg\CJK@plane\space at \the\@tempdimb} 272 | \xdef\font@name{ 273 | \csname \curr@fontshape/\f@size/\CJK@plane\endcsname} 274 | \expandafter\global\expandafter\edef\csname\curr@fontshape @tblbase\endcsname{\mandatory@arg} 275 | } 276 | 277 | \def\CurrentPunctCfg{} 278 | \def\CurrentunloadedPunctCfg{} 279 | \def\CJKpunctrule{ 280 | % 281 | % First, figure out the base name of the current CJK font 282 | \ifx\TTFslant\undefinded 283 | % --- Method 1: extract the name through NFSS (hacky!!!) 284 | %% \expandafter \ifx \csname 285 | %% \CJK@enc/\CJK@family/\CJK@series/\CJK@shape.tbl\endcsname \relax 286 | %% \bgroup 287 | %% \def\CJK@plane{25} 288 | %% \usefont{\CJK@enc}{\CJK@family}{\CJK@series}{\CJK@shape} 289 | %% \get@external@font 290 | %% \expandafter\CJKpunct@get@tbl\external@font\end 291 | %% \egroup 292 | %% \fi 293 | %% \expandafter\let \expandafter \CJK@ttt@punct \csname 294 | %% \CJK@enc/\CJK@family/\CJK@series/\CJK@shape.tbl\endcsname 295 | %%Wenchang SUN 20051014 296 | \expandafter \ifx \csname 297 | \CJK@enc/\CJK@family/\CJK@series/\CJK@shape @tblbase\endcsname \relax 298 | \savebox\voidb@x{\CJKchar{"D5}{"E2}} 299 | \fi 300 | \expandafter\lowercase\expandafter{\expandafter 301 | \edef\expandafter\CJK@ttt@punct\expandafter{\csname 302 | \CJK@enc/\CJK@family/\CJK@series/\CJK@shape @tblbase\endcsname}} 303 | \else 304 | % --- Method 2: assume the base name of the current CJK font 305 | % is of the form \lowercase{\CJK@@@enc \CJK@family} 306 | % drawback: does not always work (e.g., c19com.fd) 307 | \expandafter\lowercase\expandafter{\expandafter 308 | \edef\expandafter\CJK@ttt@punct\expandafter{\CJK@@@enc\CJK@family}} 309 | \fi 310 | 311 | \ifx\CJK@ttt@punct\CurrentPunctCfg \else 312 | \expandafter \ifx \csname CJKpunct/\CJK@ttt@punct.tbl\endcsname \relax 313 | \IfFileExists{\CJK@ttt@punct.tbl} 314 | {\edef\CJK@temp{\CJK@ttt@punct.tbl}} 315 | {\typeout{\CJK@ttt@punct.tbl not found, using gbksong.tbl} 316 | \def\CJK@temp{gbksong.tbl}} 317 | \bgroup 318 | \catcode`\\=0 \catcode`\%= 14 \catcode`\^^Z=10 % 319 | \catcode`\^^I=10 \catcode`\ =10 \catcode`\^^M=5 \catcode`\@=11 % 320 | \catcode`.=12 \catcode`,=12 \catcode`-=12 \catcode`+=12 % 321 | \catcode`0=12 \catcode`1=12 \catcode`2=12 \catcode`3=12 % 322 | \catcode`4=12 \catcode`5=12 \catcode`6=12 \catcode`7=12 % 323 | \catcode`8=12 \catcode`9=12 % 324 | \catcode`G=11 \catcode`B=11 \catcode`K=11 \catcode`p=11 % 325 | \catcode`u=11 \catcode`n=11 \catcode`c=11 \catcode`t=11 % 326 | \endlinechar=`\ % 327 | \iffalse 328 | %--- Method 1: directly input the .tbl file 329 | \IfFileExists{\CJK@temp} 330 | {\input{\CJK@temp}} 331 | {\typeout{Warning: file \CJK@temp\space not found!!!}} 332 | \else 333 | %--- Method 2: save the .tbl file in a token list to avoid reloading it 334 | \let\GBKpunct\relax % ??? To prevent \GBKpunct from being expanded 335 | \openin0 \CJK@temp 336 | % FIXME: howto display full pathname? 337 | \message{(\CJK@temp)} 338 | \ifeof0 % 339 | \typeout{Warning: file \CJK@temp\space not found!!!} 340 | \global\expandafter\def\csname CJKpunct/\CJK@ttt@punct.tbl\endcsname{} 341 | \else 342 | \@temptokena={} 343 | \loop \ifeof0 \else 344 | \read0 to\CJK@temp 345 | \@temptokena=\expandafter\expandafter\expandafter{\expandafter\the 346 | \expandafter\@temptokena\CJK@temp} 347 | \repeat 348 | \expandafter\def\expandafter\CJK@temp\expandafter{\the\@temptokena} 349 | \global\expandafter\let\csname CJKpunct/\CJK@ttt@punct.tbl\endcsname 350 | \CJK@temp 351 | \fi 352 | \closein0 353 | \fi 354 | \egroup 355 | \fi 356 | \csname CJKpunct/\CJK@ttt@punct.tbl\endcsname % Execute tokens 357 | \global\let\CurrentPunctCfg\CJK@ttt@punct 358 | \fi 359 | } 360 | 361 | \def\CJK@read@cfg{ 362 | \ifx \CJK@read@cfg@done \undefined % only load XXXkern.cfg once 363 | \IfFileExists{\CJK@@@enc kern.cfg} 364 | {{ 365 | \catcode`\\=0 \catcode`\%= 14 \catcode`\^^Z=10 % 366 | \catcode`\^^I=10 \catcode`\ =10 \catcode`\^^M=5 \catcode`\@=11 % 367 | \catcode`.=12 \catcode`,=12 \catcode`-=12 \catcode`+=12 % 368 | \catcode`0=12 \catcode`1=12 \catcode`2=12 \catcode`3=12 % 369 | \catcode`4=12 \catcode`5=12 \catcode`6=12 \catcode`7=12 % 370 | \catcode`8=12 \catcode`9=12 % 371 | \catcode`G=11 \catcode`B=11 \catcode`K=11 \catcode`p=11 % 372 | \catcode`u=11 \catcode`n=11 \catcode`c=11 \catcode`t=11 % 373 | \endlinechar=`\ % 374 | \input{\CJK@@@enc kern.cfg} 375 | }} 376 | {\typeout{Warning config file \CJK@@@enc kern.cfg not found.}} 377 | \gdef\CJK@read@cfg@done{} 378 | \fi 379 | } 380 | 381 | \let\oldCJKglue\CJKglue %% DO NOT change!! 382 | 383 | \def\CJK@loadChr#1{ 384 | \expandafter\ifx\csname CJK@#1Chx\endcsname \relax 385 | {\catcode`\%=14 \CJK@input{#1.chx}} 386 | \fi 387 | 388 | \edef\CJK@temp{#1} 389 | \ifx\CJK@temp \CJK@actualChr 390 | \else 391 | \csname CJK@#1Chx\endcsname 392 | \CJK@global\edef\CJK@actualChr{#1} 393 | \fi} 394 | 395 | \def\oldCJK@loadChr#1{ 396 | \expandafter\ifx\csname CJK@#1Chr\endcsname \relax 397 | {\catcode`\%=14 \CJK@input{#1.chr}} 398 | \fi 399 | 400 | \edef\CJK@temp{#1} 401 | \ifx\CJK@temp \CJK@actualChr 402 | \else 403 | \csname CJK@#1Chr\endcsname 404 | \CJK@global\edef\CJK@actualChr{#1} 405 | \fi} 406 | 407 | \def\CJKplainout{ 408 | \CJK@global\edef\CJK@gtemp{\CJK@actualChr} 409 | \CJK@global\def\CJK@actualChr{} 410 | \oldCJK@loadChr{\CJK@gtemp} 411 | } 412 | 413 | \def\CJKnormalout{ 414 | \CJK@global\edef\CJK@gtemp{\CJK@actualChr} 415 | \CJK@global\def\CJK@actualChr{} 416 | \CJK@loadChr{\CJK@gtemp} 417 | } 418 | 419 | \DeclareTextFontCommand{\texttt}{\CJKplainout\ttfamily} 420 | 421 | \DeclareOption{user}{\global\def\CJKpunctrule{}} 422 | \ProcessOptions\relax 423 | 424 | %%%\def\verbatim{\CJKplainout\renewcommand{\CJKglue}{}\@verbatim \frenchspacing\@vobeyspaces \@xverbatim} 425 | %%%\def\endverbatim{\if@newlist \leavevmode\fi\endtrivlist\CJKnormalout\let\CJKglue\oldCJKglue} 426 | 427 | \def\allowbreak{% 428 | \ifnum\lastkern=\@ne % 429 | % previous character is a Chinese character 430 | \unkern \unkern 431 | \edef\@tempa{\the\lastskip}% 432 | \unskip \unpenalty \hskip\@tempa \kern \m@ne sp \kern \@ne sp % 433 | \else 434 | \penalty \z@ 435 | \fi} 436 | 437 | \endlinechar `\^^M 438 | 439 | \endinput 440 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | LSP_CN 2 | ====== 3 | 4 | Linux System Programming ( Chinese Translation ) 5 | 6 | ## 免责声明 7 | 8 | 《Linux System Programming》的中文翻译,仅供爱好者学习、研究使用,不得用于其他用途,特此声明。 -------------------------------------------------------------------------------- /appendix/appA.tex: -------------------------------------------------------------------------------- 1 | % -*-coding: utf-8 -*- 2 | 3 | \defaultfont 4 | \appendix 5 | 6 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 7 | \BiAppChapter{GCC对C语言的扩展}{} 8 | GCC(GNU编译器集合, GNU Compiler Collection)为C语言提供了多种扩展功能,其中的一些扩展功能对系统程序员尤其有帮助。在本附录所提到的C语言功能扩展中,大多数为编译器提供了关于代码的行为和功能的附加信息。编译器利用这些信息可以产生更高效的机器代码。其它扩展则是对C语言的补充,尤其是在底层的系统调用方面。 9 | 10 | 最新的C语言标准---ISO C99,包括了GCC所提供的部分扩展功能。有些扩展功能与C99标准中的类似,但另外一些扩展功能在ISO C99中使用了完全不同的实现。新编写的代码应尽量遵循ISO C99标准。在本附录中,我们不会提及此类扩展,而只讨论GCC所特有的扩展功能。 11 | 12 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 13 | \BiSection{GNU C}{} 14 | GCC所支持的C语言经常被称为GNU C语言。在90年代,GNU C弥补了C语言本身的一些缺陷,提供了类似于复变量、零长度数组、内联函数、命名初始化等功能。经过十年的发展,C语言标准终于升级到了ISO C99,这导致GNU C的扩展不是很符合新的标准。然而GNU C则持续提供有帮助的特性,许多Linux程序员在其兼容C90或C99标准的代码中,仍然会使用部分GNU C的特性(通常是只使用一两个扩展功能)。 15 | 16 | 一个典型的使用GCC扩展的例子是Linux的内核,内核代码严格遵照GNU C。最近,Intel花了番功夫对Intel C编译器(ICC, Intel C Compiler)进行改造,使ICC能理解(Linux)内核所使用的那些GNU C扩展。因此,许多扩展已经变得不仅仅是只有GCC才支持了。 17 | 18 | \BiSection{内联函数}{} 19 | 将函数声明为内联(inline),编译器就会将该函数的整段代码复制到函数的调用地址。编译器直接运行函数本身,而不是将其存储在外部并在调用时跳转至该函数。这样处理既可以省去了函数调用的开销也可以在函数调用地址进行可能的优化(因为编译器能够将调用函数和被调用函数一起进行优化)。当函数的参数在调用时是常量时,后者尤其有效。然而,将函数代码拷贝到每个调用它的地方,必然会增加整体代码长度。因此,只有当函数很小很简单,或者调用次数不是很多的时候,才可以将其声明为内联函数。 20 | 21 | GCC支持inline关键字已经很多年了,使用inline就是指示编译器将函数进行内联。C99标准中这样规定inline关键字: 22 | \begin{lstlisting} 23 | static inline int foo (void) { /* ... */ } 24 | \end{lstlisting} 25 | 但从技术上讲,inline关键字只是一种提示,它仅仅是建议编译器对函数进行内联。GCC在此基础上提供了扩展功能,可以指定编译器总是将指定函数进行内联,使用方法如下: 26 | 27 | \begin{lstlisting} 28 | static inline __attribute__ (( always_inline)) int foo (void){ /*...*/ } \right)} 29 | \end{lstlisting} 30 | 内联函数的一个显而易见的用途是来替代预处理宏(preprocessor macro)。GCC中的内联函数与宏的行为一样,而且还可以进行类型检查。下面的这个宏: 31 | \begin{lstlisting} 32 | #define max(a,b) ({ a > b ? a : b; }) 33 | \end{lstlisting} 34 | 可以使用以下的内联函数替代: 35 | \begin{lstlisting} 36 | static inline max (int a, int b) 37 | { 38 | if (a > b) 39 | return a; 40 | return b; 41 | } 42 | \end{lstlisting} 43 | 程序员一般会过度使用内联函数。在大多数现代的系统架构,尤其是x86上,函数调用的开销非常非常的低。只有在非常需要的情况下才使用内联函数。 44 | 45 | \BiSection{禁用内联}{} 46 | 在主动优化模式中,GCC会自动选择适合内联的函数,并对其进行内联。一般情况这都是一个不错的处理方式,但有时程序员能判断出函数内联不会正常工作。比如,当使用\verb+__builtin_return_address+时(本附录稍后介绍),内联就可能产生问题。使用noinline可以禁用内联函数: 47 | \begin{lstlisting} 48 | __attribute_ _ ((noinline)) int foo (void) { /* ... */ } 49 | \end{lstlisting} 50 | 51 | \BiSection{纯函数}{} 52 | 纯函数是指没有任何影响的函数,其返回值仅反映了函数的参数或者非易失(nonvolatile)的全局变量。对于参数或者全局变量的访问必须是只读的。对此类函数可以进行循环优化(loop optimization)和子表达式删除(subexpression elimination)。用pure关键字表明函数为纯函数: 53 | \begin{lstlisting} 54 | __attribute__ ((pure)) int foo (int val) { /* ... */ } 55 | \end{lstlisting} 56 | 57 | 常见的例子是strlen()函数。在输入相同的情况下,无论调用多少次,该函数的返回值都保持不变,因此可以从循环中提出来,仅仅调用一次即可。例如,考虑以下代码: 58 | \begin{lstlisting}因为此类函数的返回值是其唯一的出口。 59 | /* 逐字符地打印数组p中的元素的大写形式 */ 60 | for (i=0; i < strlen (p); i++) 61 | printf ("%c", toupper (p[i])); 62 | \end{lstlisting} 63 | 64 | 如果编译器不知道strlen()是纯函数,就可能在每次循环中调用一次该函数! 65 | 66 | 聪明的程序员会这样改写代码:(如果将strlen()标记为单纯函数,编译器也会按如下代码处理) 67 | \begin{lstlisting} 68 | size_t len; 69 | 70 | len = strlen (p); 71 | for (i=0; i < len; i++) 72 | print ("%c", toupper (p[i])); 73 | \end{lstlisting} 74 | 75 | 附带说一下,更聪明的程序员(比如像本书的读者)还可能会这么做: 76 | \begin{lstlisting} 77 | while (*p) 78 | printf ("%c", toupper (*p++)); 79 | \end{lstlisting} 80 | 81 | 因为纯函数的返回值是其唯一的功能,因此让纯函数返回void是非法的,也是没有任何意义的。 82 | \BiSection{常函数}{} 83 | "常函数"是限制更严格的单纯函数。这种函数不访问全局变量,也不能将指针作为参数。因此,常值函数的返回值仅反映以值的方式传进来的参数。除了纯函数的一些优化方式之外,对常函数还可以进行其它优化。数学函数abs()是典型的常函数(假定不进行诸如保存状态或其它假借优化之名所做的小动作)。用const关键字标记常函数: 84 | \begin{lstlisting} 85 | __attribute__ ((const)) int foo (void) { /* ... */ } 86 | \end{lstlisting} 87 | 与纯函数一样,让常值函数返回void也是没有意义的。 88 | \BiSection{不返回的函数}{} 89 | 如果函数不返回(比如在函数中调用了exit()),程序员可以用noreturn关键字标记该函数,以此来通知编译器: 90 | \begin{lstlisting} 91 | __attribute__ ((noreturn)) void foo (int val) { /* ... */ } 92 | \end{lstlisting} 93 | 因为无论什么情况下,被调用的函数都不会返回,编译器则可以进行额外的优化。此类函数的返回值只能是void。 94 | \BiSection{分配内存的函数}{} 95 | 如果该函数返回指针永远不是已分配内存的别名\footnote{内存别名是指有两个或两个以上的指针指向同一个内存地址。内存别名很常见,比如我们将指针的值赋给另外的指针时,就会产生内存别名。当然,还可能有一些更复杂的情况也会出现内存别名。如果函数返回的是新分配的内存地址,则不会有其它的指针指向同一个内存地址。}(基本可以确认函数分配了新的内存并返回指向新内存的指针),程序员就可以将该函数用malloc标记,而编译器也可以进行适当的优化: 96 | \begin{lstlisting} 97 | __attribute__ ((malloc)) void * get_page (void) 98 | { 99 | int page_size; 100 | 101 | page_size = getpagesize (); 102 | if (page_size <= 0) 103 | return NULL; 104 | 105 | return malloc (page_size); 106 | } 107 | 108 | \end{lstlisting} 109 | \BiSection{强制调用函数检查返回值 }{} 110 | 属性\verb+warn_unused_result+可以指示编译器在函数返回值没有保存或没有用在条件语句中时产生警告;这不算是优化,仅是一个辅助功能: 111 | \begin{lstlisting} 112 | __attribute__ ((warn_unused_result)) int foo (void) { /* ... */ } 113 | \end{lstlisting} 114 | 当被调用函数的返回值非常重要的时候,这样处理可以让程序员所有调用函数都检查并处理了返回值。read()一类函数的返回值虽然很重要,但却经常被忽视,这时使用\verb+warn_unused_result+属性再合适不过了。这类函数不能返回void。 115 | 116 | \BiSection{将函数标记为deprecated }{} 117 | deprecated属性指示编译器,当函数被调用时产生警告信息: 118 | \begin{lstlisting} 119 | __attribute__ ((deprecated)) void foo (void) { /* ... */ } 120 | \end{lstlisting} 121 | 这有助于提醒程序员不要使用已被弃用或过时的函数。 122 | \BiSection{将函数标记为used}{} 123 | 有些情况下,函数会以编译器无法察觉的形式被调用。将函数用used标记可以指示编译器程序中使用了该函数,尽管从表面上看该函数从未被使用: 124 | \begin{lstlisting} 125 | __attribute__ ((used)) void foo (void) { /* ... */ } 126 | \end{lstlisting} 127 | 编译器会输出相应的汇编语言,而且不输出函数未被使用的警告。当静态函数仅被手写的汇编代码调用时,该属性就非常有帮助了。通常情况下(未使用used时),当某函数时没有被调用时,编译器会产生警告,并可能将该函数优化掉。 128 | 129 | \BiSection{将函数或参数标记为unused}{} 130 | unused属性指示编译器指定的函数或参数未被使用,并指示编译器不产生相应的警告: 131 | \begin{lstlisting} 132 | void foo (long __attribute__ ((unused)) value) { /* ... */ } 133 | \end{lstlisting} 134 | 这个属性可用于下列情形:使用了-W或-Wunused编译选项,有一些函数必须匹配事先定好的函数签名(这在事件驱动界面编程或者信号处理函数中很常见),而你还想捕捉到真正未使用的函数参数。 135 | \BiSection{将结构体进行打包(pack)}{} 136 | packed属性指示编译器对某类型或变量在内存中以尽可能小的内存空间保存(打包至内存),这个属性潜在的忽略了内存对齐的要求。用该属性限定结构体或联合时,其中的所有变量都会被打包。只限定一个变量时,只有被限定的变量被打包。 137 | 下列代码将结构体中的所有变量打包至所需的最小内存空间(1)。 138 | \begin{lstlisting} 139 | struct __attribute__ ((packed)) foo (void) { ... }; 140 | \end{lstlisting} 141 | 举例来说,一个结构体含有一个char类型的变量,随后是一个int类型的变量,在编译时通常会将int类型的变量对齐到char类型变量的3个字节之后,而不是将其直接放在char变量的下一个内存地址中。编译器在两个变量之间填充一些不使用的字节,以对变量进行对齐。打包后的结构体不含有这些填充字节,尽可能少的使用些内存,但不满足相应体系结构上的对齐要求。 142 | 143 | \BiSection{增加变量的内存对齐量 }{} 144 | 除了可以对变量进行打包之外,GCC还允许程序员指定给定变量的最小对齐量。在对该变量进行对齐时,编译器不使用体系结构和ABI所要求的最小对齐量,而是使用不小于该值的对齐量。比如,下列语句声明整型变量\verb+beard_length+,并指定至少进行32个字节的内存对齐(而不是常见的对32位整型变量所进行4字节对齐): 145 | 146 | \begin{lstlisting} 147 | int beard_length __attribute__ ((aligned (32))) = 0; 148 | \end{lstlisting} 149 | 通常来讲,强制指定类型的内存对齐量只有在下列情形才能用到:一是硬件的内存对齐要求比体系结构更高,二是在混写C语言和汇编代码中希望使用特定对齐量的语句时。比如说在保存处理器缓存线中经常使用到的变量,以便优化缓存行为时,就可以使用这个功能。Linux内核用到了这种技术。 150 | 151 | 除了指定最小内存对齐量之外,还可以让GCC将给定变量类型的对齐量设定为所有类型的最小内存对齐量中最大的那个值。下面这代码片段就指定了变量\verb+parrot_height+的内存对齐量为GCC中可以使用的最大值,该值通常是double型: 152 | \begin{lstlisting} 153 | short parrot_height __attribute__ ((aligned)) = 5; 154 | \end{lstlisting} 155 | 如何使用内存对齐量,通常要权衡时间和空间的消耗:经过上述方式对齐的变量会占用更多空间,但是在变量上的复制(以及其它的复杂操作)可能更省时间,因为编译器可以调用处理大块内存的机器指令,以处理大块内存。 156 | 体系结构和工具链通常会限制变量所能使用的最大的内存对齐量。在有些Linux体系结构中,链接器仅接受一个相当小的默认的对齐值。这时,使用aligned所指定的对齐量就会被设定为默认值。此外,当你指定变量的对齐量为32个字节,但系统的链接器最多只能对齐8个字节,那么变量就会使用8个字节进行对齐。 157 | \BiSection{将全局变量置于寄存器中 }{} 158 | GCC允许程序员将全局变量放在指定的寄存器中,这样变量将在程序的整个执行期内都处于该寄存器中。GCC中,这样的变量称为“全局寄存器变量”。 159 | 语法要求程序员指定具体的寄存器,下面的代码中使用寄存器ebx: 160 | \begin{lstlisting} 161 | register int *foo asm ("ebx"); 162 | \end{lstlisting} 163 | 164 | 程序员必须保证指定的寄存器不能被函数破坏(function-clobbered):就是说,指定的寄存器必须能被局部函数使用,在函数调用时会进行保存和恢复,而且不能被体系结构或者操作系统的ABI指定用作任何特殊的用途。如果选择的寄存器不合适,编译器就会产生警告信息。要是选择的寄存器合适(本例中使用的ebx在x86架构下就是合适的),编译器就会停止使用该寄存器。 165 | 当变量被频繁使用时,将其置于寄存器中可以带来显著的性能提升。虚拟机就是个很好的例子。比如说,将保存虚拟栈帧指针(virtual stack frame pointer)的变量置于寄存器中,将带来很大的好处。另一方面,要是体系结构本身的寄存器就很少(比如像x86中),优化就没什么意义了。 166 | 全局寄存器变量不能用于信号处理函数,也不能在多线程程序中使用。这些变量不能设置初始值,因为没有什么机制能让程序为寄存器设定默认值。全局寄存器变量的声明应该位于所有的函数声明之前。 167 | \BiSection{分支预测}{} 168 | GCC允许程序员对表达式的期望值进行预测,比如告诉编译器,条件语句可能是真还是假。相应地,GCC可以对代码块进行顺序调整等优化,这样可以改善条件语句的运行性能。 169 | GCC中,分支预测的语法很难看。为了让分支预测看起来舒服些,使用下列预编译宏: 170 | \begin{lstlisting} 171 | #define likely(x) __builtin_expect (!!(x), 1) 172 | #define unlikely(x) __builtin_expect (!!(x), 0) 173 | \end{lstlisting} 174 | 程序员可以将表达式分别用likely()或者unlikely()括起来,以标记为该表达式“可能为真”或者“不可能为真”。 175 | 下列例子标示分支“不可能为真”(也即,“可能为假”) 176 | \begin{lstlisting} 177 | int ret; 178 | 179 | ret = close (fd); 180 | 181 | if (unlikely (ret)) 182 | perror ("close"); 183 | \end{lstlisting} 184 | 对应的,下列例子标示分支“可能为真”: 185 | \begin{lstlisting} 186 | const char *home; 187 | 188 | home = getenv ("HOME"); 189 | if (likely (home)) 190 | printf ("Your home directory is: %s\n", home); 191 | else 192 | fprintf (stderr, "Environment variable HOME not set!\n"); 193 | \end{lstlisting} 194 | 195 | 与内联函数一样,程序员总是倾向于使用过多的分支注解。一旦开始对表达式进行预测,你就可能想去预测所有表达式。当心,只有当你事先知晓,并对表达式在几乎所有的情况下(有99\%的把握)为真或假坚信不疑的情况下,才应该将分支标记为“可能为真”或“不可能为真”。要牢记,错误的预测还不如根本不做预测。 196 | \BiSection{获取表达式的类型}{} 197 | GCC提供关键字typeof,用以取得给定表达式的类型。从语义上看,typeof关键字跟sizeof()的机理相同。比如,下列语句返回x所指向的变量的类型: 198 | \begin{lstlisting} 199 | typeof (*x) 200 | \end{lstlisting} 201 | 202 | 可以用下列语句来声明此类型的一个数组y: 203 | \begin{lstlisting} 204 | typeof (*x) y[42]; 205 | \end{lstlisting} 206 | 207 | typeof常用来编写“安全”的宏,可以用该宏来操作任意的算术值,而且仅需宏的参数取一次值即可: 208 | \begin{lstlisting} 209 | #define max(a,b) ({ \ 210 | typeof (a) _a = (a); \ 211 | typeof (b) _b = (b); \ 212 | _a > _b ? _a : _b; \ 213 | }) 214 | \end{lstlisting} 215 | \BiSection{获取类型的内存对齐量}{} 216 | GCC提供关键字\verb+__alignof__+来获取给定对象的对齐量。这个对齐量跟体系结构和ABI都有关。如果当前的体系结构没有提供必需的对齐量,关键字\verb+__alignof__+就返回ABI的推荐对齐量。否则,该关键字返回最小对齐量。 217 | 其语法跟sizeof相同: 218 | \begin{lstlisting} 219 | __alignof__(int) 220 | \end{lstlisting} 221 | 依赖于体系结构,上述代码可能返回4,因为32位整型变量通常是按照4个字节的边界进行对齐的。 222 | 该关键字还可用于左值。这种情况下,返回的对齐量是相应类型的最小内存对齐量,而不是该左值本身的对齐量。如果用aligned属性修改过最小内存对齐量(在“增加变量的内存对齐量 ”中讨论过),那么该修改可以通过\verb+__alignof__+体现。 223 | 224 | 比如,考虑以下结构体: 225 | \begin{lstlisting} 226 | struct ship { 227 | int year_built; 228 | char canons; 229 | int mast_height; 230 | }; 231 | \end{lstlisting} 232 | 和下列代码片段: 233 | \begin{lstlisting} 234 | struct ship my_ship; 235 | 236 | printf ("%d\n", __alignof__(my_ship.canons)); 237 | \end{lstlisting} 238 | 在上述代码中,尽管对于结构体的内存对齐后可能导致canons占用4个字节,但\verb+__alignedof__+表达式将返回1。 239 | \BiSection{ 结构体中成员的偏移量}{} 240 | GCC内置了一个可以获得结构体中某成员在该结构体中的偏移量的关键字。宏offsetof()在\verb++中定义,并且是ISO C标准的一部分。大多数的实现都很差劲,这些实现用到了讨厌的指针算术操作,而且代码很难懂。GCC的这个扩展更简单,而且速度可能更快: 241 | \begin{lstlisting} 242 | #define offsetof(type, member) __builtin_offsetof (type, member) 243 | \end{lstlisting} 244 | 上述调用返回了结构体类型type中成员member的偏移量,也就是,从结构体开始到该成员的字节数(从0开始)。例如,考虑下列结构体: 245 | \begin{lstlisting} 246 | struct rowboat { 247 | char *boat_name; 248 | unsigned int nr_oars; 249 | short length; 250 | }; 251 | \end{lstlisting} 252 | 实际的偏移量依赖于变量的大小,以及体系结构的对齐需求和填充行为;但在32位机上,对结构体rowboat和\verb+boat_name、nr_oars、length+调用offsetof(),将分别返回0,4和8。 253 | Linux系统中,宏offsetof()已经定义为GCC的关键字,程序员不必重新定义。 254 | \BiSection{获取函数返回地址}{} 255 | GCC提供一个以获取当前函数(或是当前函数的某个调用者)的返回地址的关键字: 256 | \begin{lstlisting} 257 | void * __builtin_return_address (unsigned int level) 258 | \end{lstlisting} 259 | 参数level指定应该返回函数调用链(call chain)中哪个函数的返回地址。取0,指定的是当前函数(f0)的返回地址;取1,指定的是函数(f0)的调用函数(f1)的返回地址;取2,指定的是调用f1的函数的返回地址;以此类推。 260 | 如果当前的函数f0是内联函数,则将返回f1的返回地址。要是觉得不能接受,可以使用\verb+__builtin_return_address+关键字(在“强制禁用内联 {noinline}”中讲过)命令编译器不将该函数作为内联函数处理。 261 | 关键字\verb+__builtin_return_address+有几种用途。可以用来调试或提供信息。还可以展开函数调用链,用以实现内部检查、故障信息转储工具(crash dump utility)、调试器等。 262 | 注意,有些体系结构只返回当前函数的地址。在这类体系结构中,非0参数可能产生随机的返回值。因此,只有参数是0时才是可移植的,非0值应该只用于调试。 263 | 264 | \BiSection{在Case中使用范围}{} 265 | GCC允许在case语句对单独的代码块指定一个值的范围。一般的语法是这样的: 266 | \begin{lstlisting} 267 | case low ... high: 268 | \end{lstlisting} 269 | 比如: 270 | \begin{lstlisting}ospec 271 | switch (val) { 272 | case 1 ... 10: 273 | /* ... */ 274 | break; 275 | case 11 ... 20: 276 | /* ... */ 277 | break; 278 | default: 279 | /* ... */ 280 | } 281 | \end{lstlisting} 282 | 在处理带ASCII码的case语句的范围时,这个功能尤其有用: 283 | \begin{lstlisting} 284 | case 'A' ... 'Z': 285 | \end{lstlisting} 286 | 287 | 288 | 注意,在省略号前后都有一个空格。不指定空格会把编译器弄糊涂,尤其是当范围是整型值的时候。应该这样写: 289 | \begin{lstlisting} 290 | case 4 ... 8: 291 | \end{lstlisting} 292 | 不要这样写: 293 | \begin{lstlisting} 294 | case 4...8: 295 | \end{lstlisting} 296 | 297 | \BiSection{void和函数指针的算术操作}{} 298 | 在GCC中,void类型的指针可以做加减法,函数指针也可以做加减法。正常情况下,ISO C标准是不允许此类指针运算的,因为不存在void指针的大小这个概念,其大小取决于指针真正指向的内容。为了进行这种运算,GCC将指向内容的大小当做是1个字节。这样,下列代码将a增加1: 299 | \begin{lstlisting} 300 | a++; /* a 是个void指针 */ 301 | \end{lstlisting} 302 | 使用编译选项-Wpointer-arith,在用到上述扩展时,GCC就会产生一条警告信息。 303 | \BiSection{让代码变得更美观并有更好的移植性}{} 304 | 我们必须承认,\verb+__attribute__+语法不是很美观。为了更好的使用本章中提到的一些扩展,甚至还需要通过预处理宏进行处理。通过调整代码外观,可以对我们使用这些扩展功能有一定的帮助。 305 | 通过使用预处理器,很容易达成这个目的。同时,还可以让这些GCC扩展具有更好的可移植性;如果编译器不是GCC(无论此时编译器是什么),那就把这些扩展定义为空。 306 | 为了达到这个目的,只需将下列代码放入头文件,并在源文件中引用该头文件: 307 | \begin{lstlisting} 308 | #if __GUNC__ >= 3 309 | # undef inline 310 | # define inline inline __attribute ((always_inline)) 311 | # define __noinline __attribute__ ((noinline)) 312 | # define __pure __attribute__ ((pure)) 313 | # define __const __attribute__ ((const)) 314 | # define __noreturn __attribute__ ((noreturn)) 315 | # define __malloc __attribute__ ((malloc)) 316 | # define __must_check __attribute__ ((warn_unused_result)) 317 | # define __deprecated __attribute__ ((deprecated)) 318 | # define __used __attribute__ ((used)) 319 | # define __unused __attribute__ ((unused)) 320 | # define __packed __attribute__ ((packed)) 321 | # define __align(x) __attribute__ ((aligned (x))) 322 | # define __align_max __attribute__ ((aligned)) 323 | # define likely(x) __builtin_expect (!!(x), 1) 324 | # define unlikely(x) __builtin_expect (!!(x), 0) 325 | #else 326 | # define __noinline /* no noinline */ 327 | # define __pure /* no pure */ 328 | # define __const /* no const */ 329 | # define __noreturn /* no noreturn */ 330 | # define __malloc /* no malloc */ 331 | # define __must_check /* no warn_unused_result */ 332 | # define __deprecated /* no deprecated */ 333 | # define __used /* no used */ 334 | # define __unused /* no unused */ 335 | # define __packed /* no packed */ 336 | # define __align(x) /* no aligned */ 337 | # define __align_max /* no aligned_max */ 338 | # define likely(x) (x) 339 | # define unlikely(x) (x) 340 | #endif 341 | \end{lstlisting} 342 | 343 | 比如,下列代码以上面定义的简写方式将函数定义为纯函数: 344 | \begin{lstlisting} 345 | __pure int foo (void) { /* ... */ } 346 | \end{lstlisting} 347 | 如果使用GCC编译,函数就被标记上pure属性。如果使用的不是GCC,预编译器将\verb+__pure+标记替换为空(no-op)。需要注意的是,我们可以在定义前指定多种属性,因此同时使用上面的几个定义,也不会有问题。 348 | 349 | 这样处理之后,代码更容易编写,看起来更漂亮,也有更好的可移植! 350 | 351 | 352 | 353 | 354 | 355 | 356 | 357 | 358 | 359 | 360 | 361 | 362 | -------------------------------------------------------------------------------- /appendix/bibliography.tex: -------------------------------------------------------------------------------- 1 | \BiAppChapter{参考书目}{} 2 | 这份书目包括了系统编程相关的推荐读物,分为四个部分进行介绍。阅读本书时并不需要读这些著作。它们是我认为在相关主题上最好的书。如果你希望深入了解某些主题,我强烈推荐这些书。 3 | 4 | 部分书籍所讨论的内容是假设本书的读者已经熟悉的(例如C语言)。某些则是对本书的有效补充,例如介绍gdb,Subversion(svn),以及操作系统设计方面的书籍。另外一些所讨论的问题超出了本书的范围(例如套接字的多线程编程)。无论其内容如何,我向大家推荐所有的书。当然,这份书单算不上详尽——你可以自由选择其它读物。 5 | 6 | \BiSection{C语言程序设计的相关书籍}{} 7 | 以下书籍介绍了系统编程的通用语言--- C语言。如果你不能熟练地编写C语言代码,以下的书籍(辅以大量的练习!)应该能在这方面提供帮助。至少,第一本——以K\&R而广为人知——是非常适合阅读的。它简短的篇幅很好的体现了C语言的简单性。 8 | 9 | \textit{The C Programming Language}, 2nd ed. Brian W. Kernighan and Dennis M. Ritchie. 10 | Prentice Hall, 1988. 11 | 这本书由C程序设计语言的作者和他的伙伴所著,被称作C语言圣经。 12 | 13 | \textit{C in a Nutshell}. Peter Prinz and Tony Crawford. O’Reilly Media, 2005. 14 | 一本很好的关于C语言和C标准库的书籍。 15 | \textit{C Pocket Reference}. Peter Prinz and Ulla Kirch-Prinz. Translated by Tony Crawford. 16 | O’Reilly Media, 2002. 17 | 一份简明扼要的C语言参考,已经更新到最新的ANSI C99标准。 18 | \textit{Expert C Programming}. Peter van der Linden. Prentice Hall, 1994. 19 | 该书对C语言中较少为人所知的部分进行了一次精彩讨论,行文中闪现着作者令人惊奇的才智和幽默感。该书充满了无厘头的笑话,不过我喜欢。 20 | \textit{C Programming FAQs: Frequently Asked Questions}, 2nd ed. Steve Summit. Addison-Wesley, 1995. 21 | 22 | 这本大部头囊括了超过400个C程序设计语言的常见问题(包括答案)。许多FAQ在C语言专家眼中是小菜一碟,但对于一些重要问题的问答,即使是最博学的C程序员都会被雷到。如果你能解决所有这些“怪物”,你绝对是一个C语言忍者!该书唯一不足就没有跟上ANSI C99,而这肯定会带来一些变化(我在自己手头的书中已经做了修正)。需要注意的是,有一份在线版本的貌似已经做了更新。 23 | 24 | \BiSection{Linux编程的相关书籍}{} 25 | 下面推荐的书籍主要介绍Linux编程的相关主题,其中包括了本书没有讨论的主题(套接字,IPC,以及pthreads),和Linux编程工具(CVS,GNU Make,以及Subversion)。 26 | 27 | \textit{Unix Network Programming, Volume 1: The Sockets Networking API}, 3rd ed. W. Rich- 28 | ard Stevens et al. Addison-Wesley, 2003. 29 | 套接字API的绝对巨著;可惜并不是针对Linux的,不过最近更新到了IPv6。 30 | 31 | \textit{UNIX Network Programming, Volume 2: Interprocess Communications}, 2nd ed. 32 | W. Richard Stevens. Prentice Hall, 1998. 33 | 关于进程间通信(IPC)的绝佳讨论。 34 | 35 | \textit{PThreads Programming: A POSIX Standard for Better Multiprocessing}. Bradford 36 | Nichols et al. O’Reilly Media, 1996. 37 | 关于POSIX线程API---pthreads的评述。 38 | 39 | \textit{Managing Projects with GNU Make}, 3rd ed. Robert Mecklenburg. O’Reilly Media, 40 | 2004. 41 | 关于GNU Make---Linux上建立软件项目的经典工具的绝佳描述。 42 | 43 | \textit{Essential CVS}, 2nd ed. Jennifer Versperman. O’Reilly Media, 2006. 44 | 关于CVS---Unix系统上版本控制和源码管理的经典工具的绝佳描述。 45 | 46 | \textit{Version Control with Subversion}. Ben Collins-Sussman et al. O’Reilly Media, 2004. 47 | 关于Subversion---Unix系统上版本控制和源码管理的优秀工具的令人惊奇的叙述,由Subversion的三位作者完成。 48 | 49 | \textit{GDB Pocket Reference}. Arnold Robbins. O’Reilly Media, 2005. 50 | 一份gdb---Linux调试器的袖珍指南。 51 | 52 | \textit{Linux in a Nutshell}, 5th ed. Ellen Siever et al. O’Reilly Media, 2005. 53 | 对Linux中各种内容的快速浏览,包括许多Linux开发环境下的工具。 54 | 55 | \BiSection{Linux内核的相关书籍}{} 56 | 下面列出的两本书主要涉及Linux内核方面的主题。我们有三重理由来对该主题进行研究。首先,内核提供了对用户空间的系统调用接口。其次,内核的行为和特性会在与其上运行的应用进行交互时体现出来。最后,Linux内核代码非常优美,同时这些书很有意思。 57 | 58 | \textit{Linux Kernel Development}, 2nd ed. Robert Love. Novell Press, 2005. 59 | 该书非常适合给那些希望了解Linux内核设计实现的系统程序员阅读(很显然,我就不必提及我在该主题上的看法了)。该书不仅可作为API参考,同时也对Linux内核中使用的算法以及所做的决策也做了精彩的论述。 60 | \textit{Linux Device Drivers}, 3rd ed. Jonathan Corbet et al. O’Reilly Media, 2005. 61 | 本书是在编写Linux内核设备驱动程序方面的绝佳指南,同时也是非常棒的API参考手册。尽管针对的是设备驱动,但书中的讨论可以使各类程序员受益(包括很少探究Linux内核机制的系统程序员)。该书是我在Linux内核方面的必备书籍。 62 | 63 | \BiSection{操作系统设计的相关书籍}{} 64 | 这两本书不是针对Linux的,而是从理论上介绍操作系统设计与实现。正如我在本书所强调的那样,对你进行编程其上的系统有一个良好的认识颇有助益。 65 | 66 | \textit{Operating Systems}, 3rd ed. Harvey Deitel et al. Prentice Hall, 2003. 67 | 操作系统设计理论方面的力作,同时还包括将理论付诸实践的顶尖样例分析。在所有操作系统设计书籍中,这是我的最爱:它紧随操作系统的研究发展,易读且详尽。 68 | 69 | \textit{UNIX Systems for Modern Architectures: Symmetric Multiprocessing and Caching for Kernel Programming}. Curt Schimmel. Addison-Wesley, 1994. 70 | 71 | 尽管和系统编程的关系不大,但该书为并发的危险性和现代缓存系统提供了绝佳的描述。吐血推荐! 72 | 73 | 74 | 75 | -------------------------------------------------------------------------------- /body/Ch1.tex: -------------------------------------------------------------------------------- 1 | % -*-coding: utf-8 -*- 2 | \ifx\atempxetex\usewhat 3 | \XeTeXinputencoding "utf-8" 4 | \fi 5 | \defaultfont 6 | 7 | \chapter{简介和主要概念} 8 | 9 | 摆在你面前的是一本关于系统编程的书,你将在本书中学习到编写系统软件的相关技术和技巧。系统软件运行于系统的底层,与内核和系统核心库直接进行交互。常见的系统软件包括shell、文本编辑器、编译器、调试器、核心工具(译者注:即GNU Core Utilities, 是构成GNU系统的基本工具集,包括大部分我们常用的命令)和系统守护进程等。这些程序都是基于内核和C库完成,可以称为"纯"系统软件。其余大部分软件(如高层(high-level)GUI应用程序)则运行在更高的层次,在必要情况下,它们也会和底层直接交互。有些程序员花费整天整夜的时间编写系统软件,而有些人则很少。不管是谁,深入理解系统编程都令程序员受益匪浅。无论你把它当作是制胜的法宝,还是仅仅认为是更高层概念的基础,系统编程都是我们编写的软件的关键所在。 10 | 11 | 12 | 确切的说,这是一本关于Linux上的系统编程的书。Linux是Linus Torvalds和全球范围内松散的黑客组织写的类Unix现代操作系统。尽管Linux和Unix有着共同的目标和理念,但是Linux不是Unix,Linux遵循自己的原则,关注方方面面的需求,专注于实用功能的开发。总的来说,Linux系统编程的核心内容和任何其它的Unix系统都是一样的。然而,除了基本内容外,Linux相比于传统的Unix系统还拥有自己突出的特点,Linux还拥有大量的新增的系统调用,不同的行为和新特性。 13 | 14 | \section{系统编程} 15 | 从传统的角度讲,所有的Unix编程都是系统级别编程。这是因为在历史上,Unix系统并没有很多的高级抽象,甚至在X Window系统上进行开发工作时,我们也会接触到大量的Unix核心API。因此,可以说这本书基本上是介绍Linux程序设计的。然而,这本书并不包含系统编程环境的介绍--书中没有任何关于make的指南,它只涵盖现代Linux机器上所使用的系统编程的API。 16 | 17 | 人们常常拿系统编程和应用层编程相比,它们有不同点,也有共同点。系统编程最突出的特点是要求系统程序员必须对它工作的系统的硬件和操作系统有深入和全面的了解,当然它们还有库和系统调用上的区别。如果从编写的应用的运行层次上来看,这两者基本上没有相关的内容。但是,总的来说,从应用程序编程转移到系统编程(或者相反),都并不是一件很困难的事情。就算是应用运行于较高层次,远离系统的最底层,系统编程的知识依然是很重要的,好的方法在各种形式的编程中都同样受用。 18 | 19 | 在近几年,我们都目睹着这样一个趋势:不管是web软件(如Javascript,PHP)还是通过托管代码(如C\#或者Java)应用编程越来越远离系统编程而向着更高的层次发展。然而,这个发展并不是预示着系统编程的消亡。实际上,还有人在继续编写Javascript解析器和C\#运行支持库,而这些都是系统编程。更进一步讲,PHP和Java程序员依然可以从系统编程中受益,就如同深入理解核内部的人能在任何层次都写出更好的代码。 20 | 21 | 尽管应用编程的发展趋势如此,大部分的Unix和Linux的程序依然是系统级别编程,这其中多数为C,且基于C库和内核提供的接口。这就是传统的系统编程——Apache、 bash、cp、Emacs、init、gcc、gdb、glibc、ls、mv、vim和X,这些应用都不会很快过时的。 22 | 23 | 在系统编程的分支中,通常包括内核开发,或者至少有设备驱动的内容。但是这本书和多数系统编程的书籍一样,将不讨论内核开发。这本书将专注于所有内核之上的内容(尽管内核知识对本书很有裨益)——用户空间系统级别编程。同样,网络编程——套接字以及相关的内容——也不在本书中展开讨论。设备驱动编程和网络编程都是很宽泛的主题,已经有许多经典书籍讨论这些话题了。 24 | 25 | 什么是系统级应用接口?我怎样在Linux上编写系统级别应用程序?内核和C库到底提供了些什么?我如何优化代码?Linux还设计了什么小伎俩?相比于其它Unix版本,Linux提供了哪些巧妙的系统调用?它们是如何工作的?这些问题将在接下来的章节中一一讨论。 26 | 27 | 系统编程中有三大基石:系统调用,C库和C编译器,每一个值得好好的介绍一下。 28 | 29 | \subsection{系统调用} 30 | 系统编程始于系统调用。系统调用(通常简写为syscalls)是为了从操作系统获得服务或者资源而从用户空间——如文本编辑器,游戏等等——向内核(系统的核心)发起的函数调用。系统调用范围很广,从我们熟悉的read()和write()函数到少见的get\_thread\_area()和 set\_tid\_address()。 31 | 32 | Linux实现的系统调用数量远远少于大部分其它操作系统。举例来说,i386架构的系统调用大概在300个左右,相比而言,微软的 Windows声称上千个。在Linux的内核中,每一个机器架构(如Alpha,i386,PowerPC)都实现了各自的系统调用。因此,不同架构之间的系统调用存在着一定的区别。然而,90\%以上系统调用在所有的架构上都实现了。本书上所讨论的正好是这个公共部分的内容。 33 | 34 | \subsection{调用系统调用} 35 | 36 | 用户空间应用程序不可能直接访问内核。基于系统安全和稳定的考虑,用户空间程序禁止直接执行内核的代码或者操作内核数据。相反,内核必须提供这样一个机制,用户空间程序能够发送信号通知内核它希望调用一个系统调用。这个应用程序因此能够通过这一机制深入到内核中,执行那些内核允许执行的代码。这个机制在不同的机器各不相同,例如,在i386上,用户空间程序执行参数为0x80的中断指令int,这个指令触发系统将当前运行环境切换到内核的保护区域,内核执行终端处理函数的区域——但是什么是中断0x80的处理函数呢?除了这个系统外,没有别的系统调用处理函数。 37 | 38 | 应用程序通过机器寄存器通知内核执行哪一个系统调用,带什么参数。系统调用通过数字标注,从0开始。在i386架构上,要想请求系统调用5(正好是open()),用户空间程序必须在使用int指令前将5填写到eax寄存器中。 39 | 40 | 参数传递也通过类似的方式进行处理。还是以i386为例,寄存器被用于每一个可能的参数——寄存器ebx、ecx、edx、esi和edi顺序存储前5个参数。对于一些少见的超过5个参数的系统调用,使用一个的寄存器指向用户空间中存储所有参数的缓存区即可。当然,大部分系统调用仅有少数的参数。 41 | 42 | 其它架构处理系统调用的方式不同,但是基本的精神是一致的。作为一个系统程序员,你通常不需要知道内核是怎样处理系统调用的。这部分内容已经成为系统架构的标准调用惯例的一部分,并通过编译器和C库自动处理。 43 | 44 | \subsection{C库} 45 | 46 | C库(libc)是Unix应用程序的核心。就算你使用别的语言,C库也常常扮演着重要的角色,它常被高级的库封装,提供核心服务或者方便的系统调用。在现代的Linux系统中,C库由GNU libc提供,简称为glibc,发音是[gee-lib-see]或者更短点[glib-see]. 47 | 48 | GNU C库提供了远超过其名字所展示的内容。除了标准的C库,glibc还提供了系统调用封装,线程支持和基本应用工具。 49 | 50 | \subsection{C编译器} 51 | 在Linux中,标准的C编译器是GNU编译器工具集(gcc)。原先,gcc是GNU版本的cc,C编译器。因此,GCC表示GNU C Compiler。后来,越来越多的语言支持都添加进去了。时至今日,gcc成了GNU编译器家族的代名词。然而,gcc经常被用来调用C编译器,在这本书中,当我讨论到gcc的时候,如果没有指定上下文,指的是gcc应用程序。 52 | 53 | 54 | 因为编译器辅助实现了C标准(参阅"C语言标准")和系统的ABI(参阅"APIs和ABIs"一节),因此Unix系统(包括Linux系统)中的编译器和系统编程的联系非常紧密。 55 | 56 | \section{API和ABI} 57 | 无论现在还是将来,程序员们都希望它们写的程序可以运行在所有声称提供支持的系统上。它们希望在它们自己的Linux发行版上完成的程序也能够运行于其它的Linux发行版,同时还可以运行在其它Linux支持的架构和更新的Linux版本上。 58 | 59 | 在系统级别,影响可移植性的因素主要包括两个相互独立的定义和描述集合,一个是应用程序接口(API)另一个是应用程序二进制接口(ABI),两个都定义和描述了软件不同模块间的接口。 60 | 61 | \subsection{API} 62 | API定了软件模块之间在源代码层交互的接口。它通过提供一组标准接口(通常以函数的方式)的方式进行抽象:一个程序片段(一般是较高层次的代码,但不见得一定是)可以调用另一个程序片段(通常位于较低层次)。举例来说,一个在屏幕上显示文本的API可能是对一系列显示文本函数提炼而得来的。一个API仅仅定义接口,而我们经常说的“API”其实是对API的实现。 63 | 64 | 通常人们把API称为一个“约定”,这不大合理,至少从该术语的一般含义上来讲,API并非双向协议。API的用户(一般是高层软件)并没有给API的定义和实现提供任何实质内容,你只能按照它现在的样子使用它,或者不使用它:要或者不要,仅此而已。API所做的仅仅是在两个软件都遵循同样的API时,确保源代码兼容。也就是说,API用户在该API的实现上能成功编译。 65 | 66 | 现实中的例子是API通过C标准来定义且通过C库来实现,这些API定义了一系列基本和重要的函数,例如字符串处理函数。 67 | 68 | 在这本书中,我们经常会涉及到API,例如第三章讨论的标准I\/O。Linux系统编程中最重要的API将在本章的“标准”一节中讨论。 69 | 70 | 71 | 72 | \subsection{ABI} 73 | API定义了源代码接口,而ABI定义的则是在特定的架构上两个或者多个软件模块之间的二进制接口。它定义了一个应用如何和自己交互,如何和内核以及库进行交互。ABI必须保证二进制代码兼容,保证一段目标代码能够在任何具有同样ABI的系统上都正常运作,而不需要重新编译。 74 | 75 | ABI主要关注的问题有调用约定、字节序、寄存器使用、系统调用、链接、库行为和二进制格式。以调用规则为例,它规定了函数如何被调用,参数如何传递,哪些寄存器被保留而哪些会被破坏,以及调用者如何提取返回的结果。 76 | 77 | 尽管曾经尝试着为特定架构下不同的操作系统(特别是i386上的Unix操作系统)定义唯一的ABI,然而到目前为止还没有取得成效。相反,包括Linux在内的操作系统都尝试定义各自独立的ABI,这些 ABI和架构紧密相连。大部分的ABI涉及了机器级别的概念,如特定的寄存器或者汇编指令。因此,在Linux系统中,每一个机器架构都有自己的ABI集合,事实上,我们以机器架构的名称来称呼这些ABI,例如alpha,x86-64等。 78 | 79 | 系统编程需要有ABI的意识,但是却没有必要记住它。因为ABI没有表面上的接口,而是通过工具链(tooltrain)如编译器、链接器等来执行。但是,了解ABI的相关内容,可以帮助你写出更优化的代码,也是你编写汇编代码或者研究工具链时的绝好资料(其实,这也是系统编程)。 80 | 81 | 我们可以从互联网上获得Linux上特定架构的工具链和内核实现的ABI资料。 82 | 83 | \section{标准} 84 | Unix系统编程是门古老的艺术,Unix编程基础已经多年没有变动了。但是Unix还是像一头精力充沛的野兽。其行为在不断变化,特性不断增加。为了让这个混乱的世界变得有序,标准组织将系统接口标准化并建立官方标准。众多的标准保留了下来,但是,从技术上讲,Linux并没有遵循它们。 Linux仅力图和两个最广泛使用的标准保持兼容:POSIX和Single Unix Specification(SUS) 85 | 86 | 除了其它内容,POSIX和SUS定义了类Unix操作系统接口上的C API,它们有效的为各种兼容的Unix系统定义了系统编程,至少是从其中归纳出了通用的API集。 87 | 88 | \subsection{POSIX和SUS的历史} 89 | 在1980年中期,电气电子工程师协会(IEEE)首先开始了Unix系统的系统级别接口标准化的相关工作。自由软件运动(Free Software Movement)的创始人Richard Stallman建议使用POSIX为该标准(发音pahz-icks),其全称为Portable Operating System Interface(可移植操作系统接口)。 90 | 91 | 在1988年,这些努力开始有了成果,IEEE std 1003.1-1988(简称POSIX1988)通过。1990年,IEEE修订 POSIX标准形成了IEEE std 1003.1-1990(POSIX1990)。非强制性的实时和线程支持则在IEEE Std 1003.1b-1993 (POSIX 1993 or POSIX.1b)和IEEE Std 1003.1c-1995(POSIX 1995 or POSIX.1c)正式成文。2001年,这些非强制性标准在POSIX1990的基础上整合形成单一的标准:IEEE Std 1003.1-2001 (POSIX 2001)。最新的标准IEEE Std 1003.1-2004发布于2004年4月,所有的核心POSIX标准简称为POSIX.1,以2004年版本为最新版本。 92 | 93 | 在1980年后期到1990年初期,Unix系统的厂商卷入了一场"Unix战争"中,每个厂商都处心积虑的将各自的Unix变种定义为"Unix"。几个主要的Unix厂商通过合并Open Software Foundation(OSF)和X/Open组建了工业联盟-The Open Group。The Open Group提供认证、白皮书和兼容测试。在1990早期,当Unix战争正如火如荼的时候,The Open Group发布了“单一UNIX规范”(Single UNIX Specification,SUS)。相比于高成本的POSIX标准,SUS是免费的,因此广受欢迎。今天,SUS已经合并了最新的POSIX标准。 94 | 95 | 第一个版本的SUS发布于1994年,与SUSv1兼容的系统被标记为Unix 95. 第二个版本的SUS发布于1997年,相应的兼容系统称为UNIX 98.第三个版本的SUS,也是最新的SUS,SUSv3发布于2002年,兼容的系统标记为Unix 03.SUSv3修正和合并了IEEE Std 1003.1-2001 和其它几个标准。在这本书中,我将在被POSIX标准化的系统调用和其它接口中提及。我将提及POSIX而不是SUS因为后者包含了前者(译者注:SUS是POSIX.1标准的一个超集,定义了一些附加的接口,这些接口扩展了基本的POSIX.1规范所提供的功能--APUE S2.2.3)。 96 | 97 | \subsection{C语言标准} 98 | Dennis Ritchie和Brian Kernighan的经典著作《C程序设计语言》(Prentice Hall)自1978年首次出版后,一直扮演着非正式的C语言规范的角色。这个版本的C俗称K\&R C。C已经快速的代替了Basic而成为了微型计算机编程的通用语言。因此,为了对这个在那时已经相当流行的语言进行标准化,美国国家标准化学院(ANSI)在1983成立了一个委员会开发一个官方版本的C语言,该版本博采众家之长,引进了新的特性,同时还借鉴了C++语言的一些经验。这个过程艰苦而漫长,ANSI C最终在1989年顺利完成。 1990年,国际标准化组织(ISO)基于ANSI C进行了少数修改,批准了ISO C90。 99 | 100 | 在1995年,ISO 发布了一个新版标准(虽然很少被执行),命名为ISO C95。1999年的版本ISO C99更新了大量的内容,引进了很多新的特征,包括inline函数、新数据类型、变长数组、C++风格注释和新的库函数。 101 | 102 | \subsection{Linux和标准} 103 | 104 | 如前所述,Linux旨在和POSIX以及SUS兼容,它提供了SUSv3和POSIX.1描述的接口,包括可选的实时(POSIX.1b)和线程 (POSIX.1c)支持。更重要的是,Linux尝试着提供和POSIX和SUS要求一致的行为。总之,无法满足标准的部分即被视为bug。Linux 被认为是按照POSIX.1和SUSv3实现的,但没有经过POSIX或者SUS官方认证(特别是Linux的每个修订),所以我无法正式宣布Linux是POSIX或者SUS兼容的。 105 | 106 | 107 | 关于语言标准,Linux很幸运,gcc C编译器支持ISO C99,另外,gcc提供了很多C语言的扩展,这些扩展统称为GNU C。附录中有相关描述。 108 | 109 | Linux没有很好的向前兼容的历史,不过这些日子过得还算顺利。标准C库这样被标准描述的接口将明显的继续保持源代码兼容。二进制代码兼容至少可以通过主要的glibc版本来维持。尽管某些gcc扩展遭到反对甚至在新的gcc发布范本中被删除,但是因为C语言已经标准化,gcc将始终准确的编译合法的C程序。最重要的是,Linux内核保证系统调用的稳定,一旦系统调用在Linux内核的稳定版本上实现,那就不会再改变了。 110 | 111 | 在不同的Linux发布版中,大部分被Linux基本规范(LSB)所标准化。LSB是在Linux基金会(前身是自由标准组织 [Free Standard Group])赞助下由几个厂商负责的联合项目。LSB扩展了POSIX和SUS,添加了自己的标准。它尝试提供二进制标准,从而允许目标代码无需修改即可在兼容的系统上运行。大部分Linux厂商都在一定程度上遵循了LSB标准。 112 | 113 | \subsection{本书和标准} 114 | 115 | 本书有意避免关于任何标准的空话。大多数时候,Unix系统编程书籍必须停止对不同标准的接口的表现进行口舌之争,无论给定的系统调用是在哪个系统上实现,都不要再浪费大量篇幅进行讨论。本书仅涉及在最新版本的2.6内核、gcc 4.2编译器和C库(2.5)的Linux系统上的进行系统编程的相关知识。 116 | 117 | 因为系统接口通常是固定的(Linux内核开发人员需要小心处理,以避免破坏调用接口) ,同时系统接口还提供了一定程度上源码和二进制码的兼容性,这种方式允许我们深入Linux细节的时候,不必去关心与其它Unix系统和标准的兼容性问题。将讨论的重点放在Linux上使本书可以深入探讨最前沿的,且在未来将继续使用的Linux接口。本书详尽地介绍了Linux系统的相关细节,特别是gcc,内核等模块的实现和行为。让我们可以从专业视角洞悉高手的实践能力和优化技巧。 118 | 119 | 120 | \section{Linux编程概念} 121 | 这一节主要展现一个关于Linux环境提供的服务的简要概览。所有的Unix系统,包括Linux系统,都提供了一个共同的抽象和接口集合。事实上,这个共同点定义了Unix。如对文件和进程的抽象、管道和套接字管理的接口等等,都是Unix的核心内容。 122 | 123 | 这个概览假定你已经熟悉了Linux环境:可以熟练使用shell,使用基本命令,编译简单的C程序。这些并不是Linux的概览,也不是Linux编程环境的内容,而是进行Linux系统编程的最基本的知识。 124 | 125 | \subsection{文件和文件系统} 126 | 127 | 文件是Linux中最基本和重要的抽象。Linux遵循一切皆是文件的理念(虽然并不是像某些其它系统那么严格,如Plan9)。因此,很多的交互工作是通过读取和写入文件来完成,就算问题的目标并不是你日常所想的文件。 128 | 129 | 文件必须被打开才能被访问。文件可以以只读方式或者只写方式打开,或者两者兼有。一个打开的文件通过唯一的文件描述符进行引用,该描述符是打开文件的元数据至其本身的映射。在Linux内核中,这个描述符称为文件描述符,用一个整数表示(C语言中的类型为int),简写为fd。文件描述符在用户空间中共享,允许用户程序用文件描述符直接访问文件。大部分的Linux系统编程包括对文件描述符的打开,关闭等操作。 130 | 131 | \subsubsection{普通文件} 132 | 133 | 我们常常说起的文件,就是Linux中的普通文件。一个普通文件包含以线性字节数组方式组织的数据,通常也称为字节流。在Linux中,文件没有更进一步的组织结构或者格式。字节可以是任何值,也可以以任何方式被组织在一个文件中,在系统级别,除了字节流,Linux并没有要求文件有特定的结构。某些操作系统,如VMS,提供了高度结构化的文件,支持如记录这样的概念。Linux并没有做这样的处理。 134 | 135 | 文件中的任何字节都可以被读或者写,这些操作开始于特定的字节,也就是文件中所谓的“地址”的概念。这个地址就是文件位置或者文件偏移量。这个文件位置是内核与每一个打开的文件关联的元数据非常重要的一部分。当文件首次打开时,位置为0。通常,随着对文件的读写操作(按字节进行),文件的位置也随之增长。文件的位置也可以通过手工指定一个值,就算这个值超过了文件的结尾。在超过文件结尾之后写入字节将会导致中间的字节填充为0。尽管可以通过这样的方式在文件的末尾写入字节,但是却不允许在文件的头部之前写入字节。这种情况听上去很荒谬,实际上也没多大用处。文件位置起始于0,它不可能是负数。在文件中间写入字节将覆盖位置偏移量上的值。因此,通过在中间写入内容来扩展文件是不可行的,大部分文件写操作发生在文件的结尾,文件位置的最大值只受存储该值的 C语言类型的大小所限制,在最新的版本的Linux上是64位。 136 | 137 | 文件的大小通过字节来计算,称为文件长度。文件长度,就是组成文件的线性数组里字节的数目。文件的长度可以通过截断(truncation)来改变。一个文件可以通过删除文件结尾部分而截短为稍小的文件。令人困惑的是,根据截断操作这个名字,一个文件可以被截断成比原来更大的文件。在这种情况,文件以“0”进行填充(在文件的末尾)。文件可以为空(长度为0),不包含任何可用字节。文件最大值,如同文件位置的最大值,受限于Linux内可用于管理文件的C语言类型的大小。然而,某些特定的文件系统,也可能强加自己的限制,将最大值限定在更小的值。 138 | 139 | 同一个文件能被不同或者相同的进程多次打开,系统为每一个打开文件的实例提供唯一的文件描述符。进程能够共享文件描述符,从而允许同一描述符被多个进程使用。内核并没有对并发文件访问强加任何限制,不同的进程能够同时对同一个文件进行读写。并发访问的结果取决于独立操作的顺序,且通常是不可预测的。用户空间程序必须调整它们自己的顺序以保证并发文件访问可以同步。 140 | 141 | 文件通过文件名进行访问,但事实上,对于文件本身并不与文件名称直接关联。相反,文件通过inode(信息节点)来访问,inode使用唯一的数值进行标志。该值称为inode编号(inode number),通常简写为i-number或者ino。一个inode存储文件关联的元数据,如它的修改时间戳、所有者、类型、长度以及文件的数据的地址--唯独没有文件名。inode既是Unix文件系统在磁盘上实际物理对象,也是Linux内核中的数据结构的概念实体。 142 | 143 | \subsubsection{目录和链接} 144 | 145 | 通过inode编号来访问文件显然是一个不明智的决定(也是一个潜在的安全漏洞)。因此,人们经常使用文件名来访问文件。目录就是用来提供访问文件时所需的名字的,目录将易读的名字和inode编号进行映射。名字与inode的配对,称为链接(link)。映射在物理磁盘上的形式,可以是一个简单的表格、一个哈希表或者其它任何形式,映射由内核代码针对某一特定的文件系统实现和管理。从概念上讲,一个目录可以被视为任何普通的文件,唯一的不同点是它仅仅存储名字和inode的映射。内核直接使用这个映射将文件名解析为inode。 146 | 147 | 当用户空间应用请求打开一个指定的文件时,内核打开包含指定文件名的目录,然后搜索该文件。内核根据文件名获取inode编号,然后根据inode编号中找到对应的inode。inode包含了文件相关的元数据,其中包括文件数据在磁盘上的存储位置。 148 | 149 | 150 | 最初,磁盘上只有根目录,这个目录通常标记为/。但我们所知道的是,系统上有很多目录。那么内核怎么知道该到哪一个目录查找给定的文件名呢? 151 | 152 | 如同之前所述,目录和普通文件相似,事实上,它们甚至也有关联的inode。因此,目录内的链接能够指向别的目录的inode。这也意味着目录可以嵌套到别的目录中,形成目录层次。这样就允许使用所有Unix用户都熟悉的路径名来查找文件,如/home/blackbeard/landscaping.txt. 153 | 154 | 当内核打开类似的路径名时,它通过遍历路径上的每一个目录项(directory entry,在内核中称为dentry)来查找下一项的inode。在前面的例子中,内核从/开始,获取home的inode,跳转到那,然后获取 blackbeard的inode,再进入该项,最终找到landscaping.txt的inode。这个操作过程称为目录或者路径解析。内核也使用缓存(称为dentry cache)来存储目录解析的结构,提供时间局部性支持,加快查询速度。时间局部性支持,我们将在后续章节讨论。 155 | 156 | 一个从根目录开始的路径名称为完全指定(fully qualified)的,也叫做绝对路径。一些路径并不是完全指定的,相反,它们只是相对于其它目录(例如:todo/plunder)。这些路径称为相对路径。当遇到相对路径时,内核在当前的工作目录下进行路径解析。从当前工作目录开始,内核首先查找目录todo,从那里内核获取plunder的 inode。 157 | 158 | 虽然目录可以看成是普通的文件,但是内核不允许像操作普通文件一样打开和操作它们。相反,它们必须通过几个特殊的系统调用来操作它们,不管在什么情况下,这些调用仅允许进行两个操作:添加链接和删除链接。如果允许用户空间绕过内核的管理而进行目录操作,那么一个非常简单的错误都可能导致文件系统崩溃。 159 | 160 | \subsubsection{硬链接} 161 | 162 | 从概念上看,到目前为止还没有任何内容涉及防止多个名字解析到同一个inode上。事实上,这样做是可以的。我们把将不同名字映射到同一个indoe信息节点的多个链接称为硬链接。 163 | 164 | 在复杂的文件系统结构中,硬链接允许多个路径名指向相同的数据。硬链接可以在同一个目录下,也可以在不同的目录中,无论在哪种情况下,内核完全可以将路径名解析到正确的信息节点上。例如,/home/bluebeard/map.txt 和/home/blackbeard/treasure.txt 都可以硬链接到指定的inode上。 165 | 166 | 删除目录结构中的一个文件将会引发一个unlink操作,该操作将文件名和inode的映射信息从目录中移除。然而,因为Linux支持硬链接,文件系统不能在每一次unlink操作都移除inode以及和它关联的数据。如果在文件系统别的地方存在另一个硬链接怎么办?为了保证每个文件在所有的链接都移除后才彻底删除文件,每个inode还包含一个链接计数(link count)来跟踪文件系统中指向该文件的硬链接数目。当路径名解除链接,链接计数将减1。当它为0的时候,inode和它关联的数据才正真的从文件系统中删除。 167 | 168 | \subsubsection{符号链接} 169 | 170 | 因为inode编号在自己文件系统之外没有任何意义,所以不能跨文件系统建立链接。为了允许跨越文件系统建立链接,Unix系统还实现了符号链接(通常简称为symlinks)。 171 | 172 | 符号链接看上去像普通文件,每个symlink都有自己的inode和包含被链接文件完整路径名的数据块。这意味着符号链接可以指向任何地方,包括不同文件系统上的文件和目录,甚至不存在的文件和目录。指向不存在文件的符号链接称为坏链接。 173 | 174 | 相比硬链接,符号链接解析需要更多开销。因为有效的解析符号链接需要解析两个文件:符号链接和被链接的文件。硬链接不需要额外的开销,因为一次或多次进入文件系统访问被链接的文件并没有任何区别。尽管符号链接的解析的开销不大,但仍然被认为是消极的。 175 | 176 | 相比硬链接,符号链接缺少一定的透明性。使用硬链接是完全透明的,实际操作中,它需要找出被链接文件是否被多次链接。而操作符号链接需要特殊的系统调用。符号链接作为一种文件访问的快捷方式而不是文件系统内部链接时,这种透明性的缺乏也具有一定的积极意义。 177 | 178 | \subsubsection{特殊文件} 179 | 180 | 特殊文件是以文件方式表示的内核对象。一直以来,Unix系统支持了一些不同的特殊文件,Linux支持四种类型的特殊文件:块设备文件、字符设备文件、命名管道和Unix域套接字。特殊文件是将某些抽象融入文件系统的一种方法,是一切皆文件理念的实践。Linux提供了创建特殊文件的系统调用。 181 | 182 | 对Unix系统的设备进行访问通过设备文件来实现,设备文件的表现和特征和文件系统中的普通文件一样。设备文件可以被打开、读取和写入,以此允许用户空间程序访问和操作系统上的(物理和虚拟的)设备。Unix的设备通常分为两类:字符设备和块设备。每种设备类型都有自己的专用设备文件。 183 | 184 | 访问字符设备如同访问字节线性队列。设备驱动程序将字节按序写入队列,用户空间程序则按照字节被写入队列的顺序进行读取。键盘就是典型的字符设备。如果你敲入"peg",应用程序将从键盘设备中读取p,然后是e,最后是g。当没有更多的字符需要读取时,设备返回end-of-file(EOF)。漏读数据或者以任何其它的顺序读取都没有意义。字符设备通过字符设备文件(character device file)进行访问。 185 | 186 | 相比之下,块设备则不同,它以字节数组的方式进行访问。设备驱动将字节映射到可寻址的设备上,用户空间可以自由的以任何顺序访问数组中的任何字节,你可以读取字节12,字节7然后再读字节12。块设备通常是存储设备、硬盘、软盘、CD-ROM驱动器和闪存都是典型的块设备,它们通过块设备文件(block device files)进行访问。 187 | 188 | 命名管道(通常叫FIFOs,是“先进先出”的简称)是一种以文件描述符为信道的进程间通信(IPC)机制,通过一种特殊文件进行访问。普通管道是将一个程序的输出以“管道”的方式传送给另一个程序,并做为该程序的输入。它们通过系统调用在内存中创建而不在任何文件系统中存在。命名管道和普通管道一样,但是通过文件进行访问。称为FIFO特殊文件,不相关的进程也可以访问这个文件而进行交互。 189 | 190 | 套接字是最后一种类型的特殊文件。套接字是进程间通信中的高级形式,它允许不同进程进行通信,不仅仅是同一台机器,不同机器也可以。事实上,套接字是网络和因特网编程的基础。它们演化出多个变种,包括Unix域套接字,这是本地机器进行交互的套接字格式。相比网络上的套接字交互需要通过主机名和端口对来确定交互的目标,Unix域套接字使用文件系统上的特殊文件进行交互,该文件称为套接字文件。 191 | 192 | \subsubsection{文件系统和名字空间} 193 | 194 | 如同所有的Unix系统一样,Linux提供了一个全局统一的文件和目录的名字空间。某些操作系统将磁盘和驱动器分割成独立的名字空间。例如,软盘上的文件可能通过A:\textbackslash plank.jpg文件名进行访问,而硬盘位置为C:\textbackslash。在Unix中,同样在软盘上的文件则通过/media/floppy/plank.jpg或者/home/captain/stuff/plank.jpg来访问,它和其它介质中的文件是在同一个名字空间下的。也就是说,在Unix中的命名空间是统一的。 195 | 196 | 文件系统是以合法层次结构组织的文件和目录的集合。文件系统能从全局的文件和目录的名字空间独立的添加和移除。这些操作称为挂载(mounting)和卸载(unmounting)。每个文件系统都要挂载在名字空间中特定的位置,这个位置称为挂载点。文件系统的根目录可以通过挂载点访问。例如,挂载CD到/media/cdrom,然后就可以通过访问挂载点来访问CD上的文件系统的根目录。第一个被挂载的文件系统位于名字空间的根部/,称为根文件系统。Linux系统总有一个根文件系统。除此之外,可在其它的挂载点挂载其它的文件系统。 197 | 198 | 文件系统一般来讲是存在于物理介质上的(如存在磁盘上),同时Linux也支持存储在内存上的虚拟文件系统和跨网络的网络文件系统。物理文件系统存在于如CD、软盘、闪存或者硬盘等块存储设备。其中一些设备是可分区的,这意味着它们可以切分成多个独立操作的文件系统。Linux支持大部分的文件系统(包含了大部分用户所希望的文件系统),例如媒体文件系统(media-specific filesystems)(如ISO9660),网络文件系统(NFS),原生文件系统(ext3),其它Unix系统的文件系统(XFS)以及非 Unix文件系统(FAT)。 199 | 200 | 块设备最小访问地址单元为扇区,扇区是设备的物理单位。扇区一般是2的指数倍,通常为512字节。块设备无法转移或者访问比扇区更小的数据单元。所有的I/O操作都发生在一个或多个扇区上。 201 | 202 | 同样,文件系统中最小的逻辑地址单元是块,块是文件系统中的抽象 而不是对物理介质的抽象,块通常是2的指数倍与扇区大小的乘积。块一般大于扇区的大小,但是必须小于页的大小(最小可访问的内存管理单元,一个硬件部件)。普通块大小为512B,1KB和4KB。 203 | 204 | 从历史的角度讲,Unix系统仅有单一共享命名空间,系统上所有的进程和用户都可见。Linux另辟蹊径,支持进程独立的名字空间,允许每一个进程拥有一个系统文件和目录层次的唯一视图。默认情况下,子进程继承父进程的名字空间,但是一个进程可以通过选择一系列挂载节点和独立的根目录来创建自己的名字空间。 205 | 206 | \subsection{进程} 207 | 208 | 如果说文件是Unix系统最重要的抽象概念,那么进程仅次于文件。进程是执行中的目标代码:活动的、生存的、运行的程序。除了目标代码,进程还包含数据、资源、状态以及虚拟化的计算机。 209 | 210 | 进程从可执行目标代码开始其生命周期。这些目标代码具有内核能够解析的可执行格式(Linux下最常用的格式是ELF),且可以由机器执行。可执行格式代码包含有元数据,多个代码和数据段。“段”是加载到线性内存块的线性目标代码块。所有片段内的字节将一视同仁,赋予相同的权限,一般也用于同样的目的。 211 | 212 | 最重要和通用的段莫过于代码段,数据段和bss段。代码段包含可执行代码和只读数据,如常量,经常标记为只读和可执行。数据段包含已初始化的数据,如定义了值的C变量,通常标记为可读写的。bss段包含未初始化的全局数据,因为C标准规定C变量的默认值全为0,因此没有必要在磁盘上的目标代码中保存这些0。相反,目标代码可以简单的列举bss段中未初始化的变量,内核将映射0页面(全0的内存页)到那个加载进内存的段,为了优化性能人们设计了bss段。这个名称带有几分历史痕迹,它是block started by symbol,或者block storage segment的缩写。其它ELF中可执行的通用段都是绝对地址段(absolut section)(包含不可再定位符号)和未定义段(容器)。 213 | 214 | 一个进程还和由内核仲裁和管理的系统资源关联,进程典型的资源请求和操作只能通过系统调用。资源包括计时器,挂起信号量、打开文件,网络连接,硬件和进程通信。一个进程的资源,进程相关的数据和统计信息都存储在内核中该进程的进程描述符中。 215 | 216 | 进程是一种虚拟的抽象。Linux内核支持抢占式多任务和虚拟内存,它给进程提供了虚拟处理器和内存的虚拟视图。从进程的视角看,系统完全由该进程控制。也就是说,尽管给定的进程和其它的进程共用调度,但是看起来好像它在独立控制整个系统。系统将无缝透明的重新进行进程调度,将系统的处理器和所有进程共享,而进程不会感到区别。类似的,每一个进程获得一个独立的线性地址空间,就像它独立控制整个系统内存。通过虚拟内存和分页调度,内核允许多个进程共存在系统上,每个进程操作都有自己的地址空间。内核通过现代处理器的硬件支持来管理这种虚拟化,它使得操作系统能够并发管理多个独立的进程。 217 | 218 | \subsubsection{线程} 219 | 220 | 一个进程包含一个或多个执行线程(通常只叫线程),线程是进程中的活动单位。线程是一种抽象,它负责执行代码和维护进程的运行状态。 221 | 222 | 大部分进程只包含一个线程,它们被称为单线程的(single-thread),包含多个线程的进程称为多线程的(multithreaded)。从传统上讲,因为Unix保持简洁、期望加快进程创建时间、保持健壮的进程通信机制,这些都减少了对线程的需求。可以说,Unix程序被单线程化了。 223 | 224 | 线程包括栈(如同在非线程系统上的进程栈,主要用于存储局部变量)、处理器状态、目标代码的当前位置(通常是处理器的指令指针)。进程剩下的部分由所有线程共享。 225 | 226 | Linux内核实现了一个独特的线程视图:它们是偶然共享某些资源的(大多数情况下是一个地址空间)进程。在用户空间,Linux根据 POSIX1003.1c实现线程(pthread)。目前Linux线程实现的名称为Native POSIX Threading Library(NPTL)是glibc库的一部分。 227 | 228 | \subsubsection{进程体系} 229 | 230 | 每一个进程都由一个唯一的正整数标识,即进程ID(pid)。第一个进程的pid是1,接下来每一个进程接受一个新的唯一的pid。 231 | 232 | 在Linux中,进程有一个严格的层次结构,这就是广为人知的进程树。进程树以第一个进程,也就是init进程(一般是init(8)程序)为根。新进程通过 fork()系统调用创建。fork()复制了调用进程,而原进程称为父进程,新进程称为子进程。除了第一个进程外,每一个进程都有父进程。如果父进程在先于子进程终止,内核将init进程指定为它的父进程。 233 | 234 | 如果进程终止,它并不会立即从系统中移除。相反,内核将在内存中保存进程的部分内容,允许父进程查询该进程终止的状态,这被称为终止进程等待。一旦父进程已经确认它的终止的子进程,子进程就完全的删除了。如一个进程已经终止,但父进程尚未获知它的状态,则称为僵尸进程(zombie)。 init进程等待其所有的子进程,保证它的子进程不会永久处于僵死状态。 235 | 236 | \subsection{用户和组} 237 | 238 | Linux中通过用户和组进行认证。每个用户和唯一的正整数关联,称为用户ID(uid)。每一个进程与一个用户ID关联,用来识别运行这个进程的用户,一般称为进程的真实uid(real uid)。在Linux内核中,uid是用户的唯一标识。但用户一般都是通过用户名而不是数字id来指代自己或者其它用户。用户名和它们对应的用户id存储在/etc/passwd中,而库例程将其用户名映射到相应的uid上。 239 | 240 | 在登陆的过程中,用户向login(1)程序提交用户名和密码。如果提供的用户名和密码都正确,login(1)程序将根据/etc/passwd为用户生成一个登陆shell(login shell),并将用户id作为进程的uid。子进程继承父进程的uid。 241 | 242 | uid 0 是超级用户root的用户id。 超级用户拥有做任何事情的特权,例如只有root用户有权限修改进程的uid。因此,login(1)的用户为超级管理员。 243 | 244 | 除了真实UID(real uid)之外,每个进程有一个有效UID(effective uid),一个保留uid(saved uid)和文件系统uid(filesystem uid)。 真实UID(real uid)是启动进程的用户,有效UID(effective uid)可以使进程在其它用户的权限下运行,保留uid(saved uid)保存原来的有效UID(effective uid),它的值决定了用户将切换到哪个有效UID(effective uid)中。文件系统uid通常和有效UID(effective uid)相等,用来检测文件系统的访问权限。 245 | 246 | 每一个用户都归属于一个或者多个组,包括列在/etc/passwd中的基本组(primary group)或登录组(login group),也可能是/etc/group中其它附加组。 每一个进程因此也有一个组ID(gid),因此也有真实gid(real gid),有效gid(effective gid),保留gid(saved gid)以及文件系统gid(filesystem gid)。进程和用户登入组关联,和其它附加组没有关系。 247 | 248 | 一些安全机制只允许进程在满足特定权限时才能进行某些操作。传统的Unix的原则非常简单:uid为0的进程可以访问的资源,其它的进程都不可访问。近来,Linux采用了更有效率的机制来代替传统的安全机制,它取消了简单的二元判断方式,允许内核进行更细粒度的访问控制设置。 249 | 250 | \subsection{权限} 251 | 252 | Linux上的标准文件权限和安全机制与Unix一致。 253 | 254 | 每一个文件都有一个所有者,所属组以及权限位集。这些位描述了所有者、所属组以及其它人对文件进行读、写和执行的权限。这三类每一个对应三个位,共9位。 文件所有者和权限信息存储在文件的indoe中。 255 | 256 | 对于普通文件,权限是很显然的,它们已经清楚表明读文件,写文件和执行文件的权限。虽然特殊文件实际读和写的内容由特殊文件自己确定,但是特殊文件上的读和写权限与普通文件的一样,执行权限在特殊文件上被忽略。目录的读权限是允许目录中的内容被列出,写权限允许在目录中添加新的链接,执行权限允许目录进入和使用该路径。 表格1-1列出了9个权限位,它们的8进制值(常用的9位表示方式),文本值(如ls显示的结果),还有对应的含义。 257 | \begin{flushleft} 258 | 表格1-1 权限位及其值 259 | \end{flushleft} 260 | \begin{flushleft} 261 | \begin{tabular}{p{2cm}p{2.8cm}p{2.8cm}p{3.0cm}}\toprule 262 | \rowcolor[gray]{.9} 263 | \textbf{位} & \textbf{八进制值} & \textbf{文本值} & \textbf{对应权限}\\ \midrule 264 | \textbf 8 & 400 & r-------- & 所有者可读 \\ 265 | \textbf 7 & 200 & -w------- & 所有者可写 \\ 266 | \textbf 6 & 100 & --x------ & 所有者可执行 \\ 267 | \textbf 5 & 040 & ---r----- & 组用户可读 \\ 268 | \textbf 4 & 020 & ----w---- & 组用户可写 \\ 269 | \textbf 3 & 010 & -----x--- & 组用户可执行 \\ 270 | \textbf 2 & 004 & ------r-- & 所有用户可读 \\ 271 | \textbf 1 & 002 & -------w- & 所有用户可写 \\ 272 | \textbf 0 & 001 & --------x & 所有用户可执行 \\ 273 | \end{tabular} 274 | \end{flushleft} 275 | 除了Unix的权限外,Linux还支持访问控制表(ACLs),ACLs支持更多细节、确切权限及安全控制,只是增加了管理复杂性和磁盘存储的开销。 276 | 277 | \subsection{信号} 278 | 279 | 信号是一种单向异步通知机制,信号可能是从内核发送到进程,也可能是从进程到进程,或者进程给自己。信号一般用于通知进程发生某些事件,如段错误或者用户输入Ctrl+C。 280 | 281 | Linux内核实现了大约30个信号(实际的数字由架构决定),每一个信号由一个数字常量和文本名表示。例如,SIGHUP用于表示终端挂起,在i386上的值为1. 282 | 283 | 除了SIGKILL(进程中断)和SIGSTOP(进程停止)外,进程能够根据接收到的信号进行控制。它们可以使用默认的信号处理操作,可能是中断进程、中断并做内存信息转储(coredump)、停止进程,或者什么也不做,具体的操作取决于信号值。另外,进程可以选择显式的忽略或者处理信号。忽略信号是将信号丢弃,不做处理。处理信号将执行用户编写的信号处理函数,程序将在接收到信号时跳到处理函数,信号处理程序返回后,将把程序控制权回交给原来的程序,在之前中断的指令处继续执行。 284 | 285 | \subsection{进程间通讯} 286 | 287 | 允许进程交换信息和通知彼此所发生的事件是操作系统最重要的工作之一。Linux内核实现了传统的Unix的进程间通讯(IPC)机制,包括System V和POSIX共同定义和标准化的机制,以及Linux自定义的机制。 288 | 289 | Linux支持的进程间通讯机制包括管道,命名管道,信号量,消息队列,共享内存和快速用户空间互斥体(Futexes)。 290 | 291 | \subsection{头文件} 292 | 293 | Linux系统编程离不开大量的头文件。内核和glibc为系统级编程提供了头文件。这些头文件包括标准C库(例如,)以及Unix的一些贡献(如:)。 294 | 295 | \subsection{错误处理} 296 | 297 | 不用说,检测和处理错误是极其极其重要的。在系统编程中,错误通常通过函数的返回值表示,并通过特殊的变量errno来描述。glibc对库函数和系统调用的errno提供透明支持。本书所提及的大量接口都使用这个机制来报告错误。 298 | 299 | 函数通过特殊的返回值(通常是-1,具体值取决于函数),来通知调用者所发生的错误。错误值告诉调用函数发生了错误,但是不提供发生错误的原因,errno变量用于定位错误的原因。 300 | 301 | 302 | 该变量在中定义如下: 303 | 304 | extern int errno; 305 | 306 | erron的值仅仅在errno设置函数显示错误后(通常返回-1)短时间有效,否则,任何后续成功执行的函数都可以修改其值。 307 | 308 | errno值可以直接被读写,它是可修改的左值(lvalue)。errno的值与指定错误的文本信息一一对应。预处理器\#define同样将errno映射到相应的数字值上。如,预处理器定义EACCESS等于1,表示“权限不足”,表格1-2上列举了标准定义和与错误相匹配的文字描述。 309 | 310 | \begin{flushleft} 311 | 表格 1-2 错误代码及其描述 312 | \end{flushleft} 313 | \begin{flushleft} 314 | \begin{tabular}{ccc} 315 | \toprule [1pt] 316 | \rowcolor[gray]{.9} 317 | \textbf{预处理器定义}&\textbf{描述}\\ 318 | \midrule 319 | E2BIG&参数列表太长\\ 320 | EACCESS&权限不足\\ 321 | EAGAIN&重试\\ 322 | EBADF&文件号错误\\ 323 | EBUSY&设备或资源忙\\ 324 | ECHILD&无子进程\\ 325 | EDOM&数学参数不在函数域内\\ 326 | EEXIST&文件已存在\\ 327 | EFAULT&地址错误\\ 328 | EFBIG&文件太大\\ 329 | EINTR&系统调用被中断\\ 330 | EINVAL&参数无效\\ 331 | EIO&I/O错误\\ 332 | EISDIR&是目录\\ 333 | EMFILE&打开文件太多\\ 334 | EMLINK&太多链接\\ 335 | ENFILE&文件表溢出\\ 336 | ENODEV&无此设备\\ 337 | ENOENT&无此文件或目录\\ 338 | ENOEXEC&执行格式错误\\ 339 | ENOMEM&内存用尽\\ 340 | ENOSPC&设备无剩余空间\\ 341 | ENOTDIR&非目录\\ 342 | ENOTTY&不合理I/O控制操作\\ 343 | ENXIO&无此设备或地址\\ 344 | EPERM&操作不允许\\ 345 | EPIPE&管道损坏\\ 346 | ERANGE&结果范围太大\\ 347 | EROFS&只读文件系统\\ 348 | ESPIPE&非法定位\\ 349 | ESRCH&无此进程\\ 350 | ETXTBSY&文本文件忙\\ 351 | EXDEV&跨文件系统链接\\ 352 | \bottomrule[1pt] 353 | \end{tabular} 354 | \end{flushleft} 355 | 356 | C库提供了一些函数将errno值转换到对应的文本。这些函数仅仅在错误报告时是有必要的,检查错误和处理错误操作则可以直接使用预处理器定义和errno进行处理。 357 | 358 | 第一个这样的函数是perror(): 359 | 360 | \begin{lstlisting} 361 | #include 362 | void perror(const char *str); 363 | \end{lstlisting} 364 | 365 | 这个函数向stderr(标准错误输出)打印出以str指向的字符串为前缀,中间一个冒号,然后是errno描述的当前错误所陈述的字符串。为了使输出错误更加有用,执行失败的函数的名称最好包含在该字符串中,例如: 366 | 367 | \begin{lstlisting} 368 | if (close (fd) == -1) 369 | perror ("close"); 370 | \end{lstlisting} 371 | 372 | C库还提供了streeor()和strerror\_r(),原型如下: 373 | 374 | \begin{lstlisting} 375 | #include 376 | char * strerror (int errnum); 377 | \end{lstlisting} 378 | 379 | 和 380 | \begin{lstlisting} 381 | #include 382 | int strerror_r(int errnum, char *buf, size_t len); 383 | \end{lstlisting} 384 | 385 | 前一个函数返回errnum值描述的错误的字符串指针。字符串不能被应用程序修改,但是可以被接下来的perror()和streeror()函数所修改。这些方法都不是线程安全(thread-safe)的。 386 | 387 | strerror\_r()函数是线程安全的,它向buf指向的长度为len的缓冲区写入数据。streeror\_r()在成功时返回0,失败时返回-1,具有讽刺意味的是,这个函数也在错误时设置errno。 388 | 389 | 对于某些函数,在返回类型的范围内的值都是合法的返回值。在这种情况下,errno必须在调用前被设定为0,且调用后进行检测(这些函数约定在真正发生错误时只返回非0值)。例如 390 | 391 | \begin{lstlisting} 392 | errno = 0; 393 | arg = strtoul (buf, NULL, 0); 394 | if (errno) 395 | perror ("strtoul"); 396 | \end{lstlisting} 397 | 398 | 使用errno时常犯的错误是忘记库函数和系统调用都可以修改errno。例如,以下代码是有问题的: 399 | 400 | \begin{lstlisting} 401 | if (fsync (fd) == -1) { 402 | printf (stderr, "fsync failed!\n"); 403 | if (errno == EIO) 404 | fprintf (stderr, "I/O error on %d!\n", fd); 405 | } 406 | \end{lstlisting} 407 | 408 | 如果你需要跨函数调用来保留errno的值,你需要保存该值: 409 | 410 | \begin{lstlisting} 411 | if (fsync (fd) == -1) { 412 | int err = errno; 413 | fprintf (stderr, "fsync failed: \n", strerror (errno)); 414 | if (err == EIO) { 415 | /* if the error is I/O-related, jump ship */ 416 | fprintf (stderr, "I/O error on %d!\n", fd); 417 | exit (EXIT_FAILURE); 418 | } 419 | } 420 | \end{lstlisting} 421 | 422 | 如本节前面所介绍的,在单线程程序中,errno是全局变量。然而,在多线程程序中,每一个程序都保留了自己的errno,因此是线程安全的。 423 | 424 | \section{开始系统编程} 425 | 这一章着眼于Linux系统编程的基础并展示了程序员角度的Linux系统。下一章将讨论文件I/O。当然,这包括读和写文件;然而,因为Linux实现了很多文件相关的接口,文件I/O,怎么说,比文件重要的不只是一点点。 426 | 427 | 依靠之前这些知识,然后从广阔的视角上收缩下来,是的,是时候进行真正的系统编程了。动手吧,朋友们。 428 | -------------------------------------------------------------------------------- /body/Ch3.tex: -------------------------------------------------------------------------------- 1 | \ifx\atempxetex\usewhat 2 | \XeTeXinputencoding "utf-8" 3 | \fi 4 | \defaultfont 5 | 6 | \chapter{缓冲输入输出} 7 | 8 | 让我们来回顾一下第一章中的块的概念,做为文件系统的抽象,它是I/O中最基本的概念-所有的磁盘操作都是基于块进行的。因此,当请求以块大小整数倍对齐地址时,I/O效率是最理想的。 9 | 10 | 操作效率随着系统调用次数的增多而急剧下降。例如,每次读一字节读1024次与一次读1024字节相比,显然后者效率更优。如果长度不是 block(块)的整数倍,即使每次以大于块的长度进行一系列的操作,其效率也不是最理想的。例如块的大小是1K,每次以1130字节的长度操作数据要比每次1024字节的速度慢。 11 | 12 | \section{用户-缓冲I/O} 13 | 需要对普通文件执行许多轻量级I/O请求的程序通常使用用户缓冲I/O。用户缓冲I/O是在用户空间而不是在内核中完成的,它可以在程序中设定,也可以调用标准库透明地执行。正如第二章中讨论的,出于性能方面的考虑,内核通过延迟写操作,组合相邻I/O请求和预读等操作来缓冲数据。通过不同的方法,用户缓冲的主旨也是为了提高操作效率。 14 | 15 | 以用户空间程序dd为例: 16 | \begin{lstlisting} 17 | dd bs=1 count=2097152 if=/dev/zero of=pirate 18 | \end{lstlisting} 19 | 20 | 因为参数bs=1,这个命令会进行2,097,152次操作(每次一字节)从文件/dev/zero(一个提供无限的0文件流的虚拟设备)中拷贝2M到文件 pirate中。也就是说,拷贝文件的过程会产生大约2百万次的读写操作——每次一个字节。 21 | 22 | 现在考虑相同的2M字节拷贝,但是每次使用1024字节的块: 23 | \begin{lstlisting} 24 | dd bs=1024 count=2048 if=/dev/zero of=pirate 25 | \end{lstlisting} 26 | 27 | 该操作复制相同的2M 字节内容到相同的文件中,但是前一种方式执行的读写操作次数是该种方式的1024倍。正如你在表3-1中看到的,效率提高是很显著的。表中记录了用四个只在每次拷贝块大小上有区别的 dd命令所耗费的时间(用三种不同的测量)。实际时间是总消耗的时钟时间,用户时间是在用户空间中执行程序代码的时间,而系统时间是指进程在内核中执行系统调用所消耗的时间。 28 | 29 | 表3-1. 块大小对性能的影响 30 | 31 | \begin{tabular}{cccc} 32 | Block size  &  Real time   & User time   & System time\\ \hline 33 | 1 byte    &  18.707 seconds & 1.118 seconds & 17.549 seconds\\ 34 | 1,024 bytes &  0.025 seconds & 0.002 seconds & 0.023 seconds\\ 35 | 1,130 bytes &  0.035 seconds & 0.002 seconds & 0.027 second\\ 36 | \end{tabular} 37 | 38 | 39 | 40 | 使用1024字节块大小进行操作和1字节块相比,获得了巨大的性能提升。但是,这个表也显示用一个更大的块大小(这也意味着较少的系统调用),如果块大小不是磁盘块大小的整数倍,那么会导致效率变差。即使需要更少的调用,1130字节的请求导致产生不对齐的操作,因此比1024字节的请求效率更低。 41 | 42 | 为了利用这个特性,需要预先知道可能的物理块大小。表中显式的结果表明块大小最可能是1024,1024的整数倍,或者是1024的约数。在本例中,/dev/zero的块大小实际上是4096B。 43 | 44 | \subsection{块大小} 45 | 46 | 实际应用中,块大小一般是512字节, 1024字节, 2048字节, 或4096字节。如表3-1中显示,效率的大规模提升只是通过将每次操作的数据设置为块大小整数倍或约数获得的。这是因为内核和硬件之间是通过块交互的。所以,使用块大小或者一个能够恰好能放入一个块中的值来保证请求是块对齐的,可以防止无关的内核操作。 47 | 48 | 通过用系统调用stat()(我们将在第七章讨论)或stat(1)可以轻松指定设备的块大小。 事实上,一般情况下我们不需要知道确切的块大小. 49 | 50 | 为I/O操作选择一个大小的主要目标是不要选择像1130这样一个莫名其妙的值。Unix的历史上没有块长度是1130字节的,选择这样的块大小会在第一次操作后导致I/O不对齐。但是使用块大小的整数倍或约数就可以防止不对齐的请求。只要你选择的大小保持所有操作块对齐, 效率就会好。较大的整数倍只是减少了系统调用次数。 51 | 52 | 然而,最简单的方法是用一个大小为标准块大小整数倍的缓冲区来执行I/O。 4096或8192字节的效果都不错. 53 | 54 | 但问题是程序很少以块为单位进行操作.程序往往以区域,行,和单个字符为单位进行操作,而不是抽象的块。如前所述,为了改善这种情况,程序使用用户缓冲I/O. 当数据被写入时,它会被存储在程序地址空间的缓冲区中。当缓冲区规模达到一个给定的值(缓冲区大小时),整个缓冲区会在一次操作中被写出。同理,读操作一次读入缓冲区大小且块对齐的数据。当应用程序执行不对齐的读请求时,缓冲区一块一块的给出数据。最后,当缓冲区为空时,另一个大的块对齐的区域又被读入。如果缓冲区的大小设置得当,将会有很大的效率提升。 55 | 56 | 你可以在程序中实现用户缓冲。事实上很多关键应用就是独立实现用户缓冲的。然而大部分程序使用标准I/O库(C标准库的一部分),这个库可以提供健壮而且功能强大的用户缓冲方案。 57 | 58 | \subsection{标准I/O} 59 | 60 | C标准库中提供了标准I/O库(通常简单称作stdio),其中实现了一个跨平台用户缓冲的解决方案。这个标准I/O库使用简单,而且功能强大。与其它编程语言(例如FORTAN)不同, 除了流控制和算数运算等基本支持外,C语言并没有对其它高级功能提供内嵌支持,当然也没有对I/O的内在支持。随着C语言的发展,用户们开发了一些提供核心功能的函数,例如字符串处理、数学函数库、日期时间库以及I/O库等。随着这些例程日渐成熟,在ANSI C委员会的许可下(C89),这些函数最终被归入C语言标准库。虽然C95和C99都加入了一些新的接口,标准I/O库与1989年刚刚创建的时候相比改变不大。 61 | 62 | 本章余下的部分讨论用户缓冲I/O。因为它属于文件输入输出,而且在C标准库中实现,因此打开、关闭、读写文件都是通过C标准库完成。一个程序究竟应该使用标准I/O或是自创的用户缓冲,还是直接使用系统调用,这些都需要设计者仔细权衡程序的需求和行为后才能决定。 63 | 64 | C标准通常会给每种实现保留一些的细节,而相关实现通常会加入一些扩展的特性。本章和本书的其它章节一样,主要讨论现代Linux上的接口和行为,这些接口和行为主要是用glibc实现的。在Linux偏离基本标准的时候,我们会予以指明。 65 | 66 | \subsection{文件指针} 67 | 68 | 标准I/O例程并不直接操作文件描述符。取而代之的是它们用自己唯一的标志符,即大家熟知的文件指针(file pointer)。在C标准库里,文件指针映射到一个文件描述符。文件指针由FILE类型的指针表示,FILE类型定义在中。 69 | 70 | 在标准I/O中,一个打开的文件叫做"流"(stream)。 流可以被打开用来读(输入流), 写(输出流),或者二者兼有(输入输出流)。 71 | 72 | \section{打开文件} 73 | 74 | 文件通过fopen()打开以供读写操作: 75 | \begin{lstlisting} 76 | #include 77 | FILE* fopen(const char * path, const char * mode); 78 | \end{lstlisting} 79 | 80 | 这个函数根据指定的模式打开文件path,并为它关联一个新的流。 81 | 82 | \subsection{模式} 83 | 84 | 参数模式mode描述以怎样的方式打开指定文件。 它可以是下述字符串之一: 85 | \begin{list}{} 86 | \item \textbf{r}\\ 87 | 打开文件用来读取。流定位在文件的开始处。 88 | \item \textbf{r+}\\ 89 | 打开文件用来读写。流定位在文件的开始处。 90 | \item \textbf{w}\\ 91 | 打开文件用来写入,如果文件存在, 文件会被清空。 如果文件不存在,它会被创建。流定位在文件的开始处。 92 | \item \textbf{w+}\\ 93 | 打开文件用来读写。如果文件存在,文件会被清空。如果文件不存在,它会被创建。流被设置在文件的开始。 94 | \item \textbf{a}\\ 95 | 打开文件用来追加模式的写入。如果文件不存在它会被创建。流被设置在文件的末尾。所有的写入都会接在文件后。 96 | \item \textbf{a+}\\ 97 | 打开文件用来追加模式的读写。如果文件不存在,它会被创建。流被设置在文件的末尾。 所有的写入都会接在文件后。 98 | \end{list} 99 | 给定的模式可能还有字符b,但这个值在Linux下通常会被忽略。 一些操作系统用不同的方式对待文本和二进制文件, 并且b模式指示文件用二进制打开。Linux, 和所有的符合可移植性的操作系统,以相同的方式对待文本和二进制文件。 100 | 101 | 成功时,fopen()返回一个合法的FILE指针。 失败时,它返回NULL,而且相应的设置errno。 102 | 103 | 例如,下面的代码打开/etc/manifest以供读取,并将它与一个流关联: 104 | \begin{lstlisting} 105 | FILE *stream; 106 | stream = fopen ("/etc/manifest", "r"); 107 | if (!stream) 108 | /* error */ 109 | \end{lstlisting} 110 | 111 | 112 | \subsection{通过文件描述符打开文件} 113 | 114 | 函数fdopen()将一个已经打开的文件描述符(fd)转成一个流: 115 | \begin{lstlisting} 116 | #include 117 | FILE * fdopen (int fd, const char *mode); 118 | \end{lstlisting} 119 | 120 | fdopen()的可能模式和fopen()一样,而且必许和原来打开文件描述符的模式匹配。可以指定模式w和w+,但是它们不会截断文件。流的位置设置在文件描述符指向的文件位置。 一旦文件描述符被转换为一个流, 则不应该直接在该文件描述符上进行I/O(尽管这么做是合法的)。需要注意的是文件描述符没有被复制,而只是关联了一个新的流。关闭流也会关闭相应的文件描述符。成功时,fdoepn()返回一个合法的文件指针;失败时,返回NULL。 例如, 下面的代码通过open()系统调用打开/home/kidd/map.txt,然后用已有的文件描述符创建一个关联的流: 121 | \begin{lstlisting} 122 | FILE *stream; 123 | int fd; 124 | fd = open ("/home/kidd/map.txt", O_RDONLY); 125 | if (fd == −1) 126 | /* error */ 127 | stream = fdopen (fd, "r"); 128 | if (!stream) 129 | /* error */ 130 | \end{lstlisting} 131 | 132 | 133 | \section{关闭流} 134 | 135 | fclose()函数关闭一个给定的流: 136 | \begin{lstlisting} 137 | #include 138 | int fclose (FILE *stream); 139 | \end{lstlisting} 140 | 141 | 142 | 所有被缓冲但还没有被写出的数据会被先写出。成功时,fclose()返回0。失败时返回EOF并且相应的设置errno。 143 | 144 | \subsection{关闭所有的流} 145 | 146 | fcloseall()函数关闭所有的和当前进程相关联的流,包括标准输入,标准输出,标准错误: 147 | \begin{lstlisting} 148 | #define _GNU_SOURCE 149 | #include 150 | int fcloseall (void); 151 | \end{lstlisting} 152 | 153 | 关闭之前,所有的的流会被写出。这个函数始终返回0;该函数是Linux所特有的。 154 | 155 | \section{从流中读取数据} 156 | 157 | C标准库实现了多种从流中读取数据的方法。这部分会考察三种最常用的:单个字节的读取,单行的读取,和二进制数据读取。为了从流中读数据,流必须以恰当的方式打开;也就是说,任何除了w或a的模式都可以。 158 | 159 | \subsection{单字节读取} 160 | 161 | 通常,理想的输入输出模式是每次简单地读取一个字符。函数fgetc()可以用来从流中读取单个字符: 162 | \begin{lstlisting} 163 | #include 164 | int fgetc (FILE *stream); 165 | \end{lstlisting} 166 | 167 | 这个函数从流中读取下一个字符并把该无符号字符强转为int返回。强转是为了有足够的范围来表示文件结尾符和错误:在这种情况下EOF会被返回。fgetc()的返回值必须以int型保存。把返回值保存为char类型中是一个很常见但很危险的错误。下面的例子从流中读取单个字符,检查错误,然后以字符方式打印结果: 168 | \begin{lstlisting} 169 | int c; 170 | c = fgetc (stream); 171 | if (c == EOF) 172 | /* error */ 173 | else 174 | printf ("c=%c\n", (char) c); 175 | \end{lstlisting} 176 | 177 | stream指向的流必须以可读模式打开。 178 | 179 | \subsection{把字符回放入流中} 180 | 181 | 标准输入输出提供了一个将字符放回流中的函数。这个函数允许你“偷窥”流,如果你不需要该字符的话,可以把它放回。 182 | \begin{lstlisting} 183 | #include 184 | int ungetc (int c, FILE *stream); 185 | \end{lstlisting} 186 | 187 | 每次调用把c强转成一个无符号字符并放回流中。成功时,返回c;失败时返回EOF。随后读取流会返回c。如果多个字符被放入流中,它们会以倒序的方式返回-就是说,最后推入的先返回。POSIX 指出,在中间没有读入请求时只能保证一次放回成功。然而有些实现只允许一次放回。只要有足够的内存,Linux允许无限次数的放回。一次放回当然总会成功。 188 | 189 | 如果你在调用ungetc()之后,但在执行下一个读入请求之前执行了一次定位函数(见本章后半部分'定位流')的调用,会导致所有推回的字符被丢弃。在一个进程的多个线程中确实是这样的,因为所有的线程共享一个缓冲区。 190 | 191 | \subsection{按行的读取} 192 | 193 | 函数fgets()从一个给定的流中读取一个字符串: 194 | \begin{lstlisting} 195 | #include 196 | char * fgets (char *str, int size, FILE *stream); 197 | \end{lstlisting} 198 | 199 | 这个函数从流中读取 size-1 个字节的数据,并把数据存入str中。 当所有字节读入时,空字符被存入字符串末尾。当读到EOF或换行符时读入结束。如果读到了一个换行符,'{\textbackslash}n'被存入str。 200 | 201 | 成功时返回str;失败时,返回NULL。例如: 202 | \begin{lstlisting} 203 | char buf[LINE_MAX]; 204 | if (!fgets (buf, LINE_MAX, stream)) 205 | /* error */ 206 | \end{lstlisting} 207 | 208 | POSIX 在中定义了宏LINE\_MAX:它是POSIX行控制接口能够处理的输入行的最大长度。linux的C函数库没有提供这样的限制(行可以是任意长度),但是不能和宏LINE\_MAX交互。可移植程序可以用LINE\_MAX来保证安全;在linux系统中,该值被设置的相对较高。针对linux的程序无需担心行大小的限制。 209 | 210 | \subsection{读取任意字符串} 211 | 212 | fgets()基于行的读取通常是很有用的。但很多时候它又很麻烦。有时候开发者想用一个分隔符而不是换行符。有时候开发者根本不需要一个分隔符-而且极少数情况下开发者希望分隔符留在缓冲区。从历史经验来看,在返回的缓冲区中存入换行符很少是正确的。 213 | 214 | 用fgetc()写一个fgets()并不难。例如,下面的代码片段从流中读取n-1个字节到str中,然后加上一个'\textbackslash0': 215 | \begin{lstlisting} 216 | char *s; 217 | int c; 218 | s = str; 219 | 220 | while (--n > 0 && (c = fgetc (stream)) != EOF) 221 | *s++ = c; 222 | *s = '\0'; 223 | \end{lstlisting} 224 | 225 | 这段程序可以扩展为在任意指定的分隔符 d 处停止(在本例中d不能是空字符): 226 | \begin{lstlisting} 227 | char *s; 228 | int c = 0; 229 | s = str; 230 | 231 | while (--n > 0 && (c = fgetc (stream)) != EOF && (*s++ = c) != d) 232 | ; 233 | if (c == d) 234 | *--s = '\0'; 235 | else 236 | *s = '\0'; 237 | \end{lstlisting} 238 | 239 | 除了在缓冲区中存入换行符,将d设置为'{\textbackslash}n'可以提供和fgets()类似的功能,。 240 | 241 | 根据fgets()的实现,这个实现方式可能要慢些,因为它重复调用了很多次fgetc()。 然而,这和我们一开始的dd例子不同。虽然这段代码出现了过多的函数调用,但它没有进行过多的系统调用和dd程序中bs=1引起的不对齐I/O负担,相对来讲后者是更大的问题。 242 | 243 | \subsection{读取二进制文件} 244 | 245 | 一些应用程序不只是读取字符。有时候开发者想读写复杂的二进制数据,例如C中的结构。因此,标准输入输出库提供了函数fread(): 246 | \begin{lstlisting} 247 | #include 248 | size_t fread (void *buf, size_t size, size_t nr, FILE *stream); 249 | \end{lstlisting} 250 | 251 | 调用fread()会从输入流中读取nr个数据,每个数据有size个字节,并将数据放入到buf所指向的缓冲区。文件指针向前移动读出数据的长度。 252 | 253 | 读入元素的个数(不是读入字节的个数!)被返回。这个函通过返回一个比nr小的数表明读取失败或文件结束。不幸的是,在没有使用ferror()和feof()(见后面"错误和文件结束")的情况下,不可能知道发生了这两种情况的哪一个。 254 | 255 | 因为变量大小,对齐,填充,字节序的不同,一个程序写的二进制文件,对另一个程序可能是不可读的,即使是该程序在其它架构上的版本也可能是无法读取的。 256 | 257 | fread()最简单的例子是从给定流中读取一个线性大小的元素: 258 | \begin{lstlisting} 259 | char buf[64]; 260 | size_t nr; 261 | 262 | nr = fread (buf, sizeof(buf), 1, stream); 263 | if (nr == 0) 264 | /* error */ 265 | \end{lstlisting} 266 | 267 | 当我们学习和fread()相对应的fwrite()时,我们会看一些更复杂的例子。 268 | 269 | \section{向流中写数据} 270 | 271 | 和读取相同,C标准库定义了许多用来将数据写入流中的函数。在这一部分我们会学习三个最常用的写数据的方法:单个字节的写入,字符串写入,和二进制写入。这些不同的写入方法对于缓冲I/O都是适用的。为了向流中写数据,流必须以恰当的输出流的模式打开;就是说,除了r的所有合法的模式。 272 | 273 | \subsection{对齐的讨论} 274 | 所有的机器设计都有数据对齐的要求。程序员倾向于把内存想成一个简单的字节数组。但是处理器并不以字符大小对内存进行读写。相反,处理器以特定的粒度(例如2,4,8或16字节)来访问内存。因为每个处理的地址空间都从0地址开始,进程必须从一个特定粒度的整数倍开始读取。 275 | 因此,C变量的存储和访问都要是地址对齐的。总的来说,变量是自动对齐的,这指的是和C数据类型大小相关的对齐。例如,一个32位整数以4个字节对齐。用另一种说法就是一个int需要被存储在能被4整除的内存地址中。 276 | 访问不对齐的数据在不同的体系结构上有不同程度的性能损失。一些处理器能够访问不对齐的数据,但是会有一个很大性能损失。有些的处理器根本不能够访问非对齐的数据,而且企图这么做会导致硬件异常。更糟的是,一些处理器为了强制地址对齐会丢弃了低位的数据,从而导致不可预料的行为。 277 | 通常,编译器自动对齐数据,而且对齐是程序员不可见的。在处理结构体,手动执行内存管理,向磁盘存储二进制数据,和进行网络通信时,对齐都非常重要。因此系统程序员应当熟练掌握这些方法。 278 | 第八章会更深入的讨论对齐的内容。 279 | 280 | 281 | \subsection{写入单个字符} 282 | 283 | 与fgetc()相对应的函数是fputc(): 284 | \begin{lstlisting} 285 | #include 286 | int fputc (int c, FILE *stream); 287 | \end{lstlisting} 288 | 289 | fputc()函数将c表示的字节(强转为了一个无符号字符)写入stream指向的流中。成功完成时,函数返回c。否则返回EOF,并且相应的设置errno。 290 | 291 | 用法很简单 292 | \begin{lstlisting} 293 | if (fputc ('p', stream) == EOF) 294 | /* error */ 295 | \end{lstlisting} 296 | 297 | 这个例子将p写入流中,这个流必须打开用于写入。 298 | 299 | \subsection{写入字符串} 300 | 301 | 函数fputs()用来往给定的流中写入一个完整的字符串: 302 | \begin{lstlisting} 303 | #include 304 | int fputs (const char *str, FILE *stream); 305 | \end{lstlisting} 306 | 307 | fputs()的调用将str指向的字符串的所有非分隔符部分写入stream指向的流中。成功时,fputs()返回一个非负整数。失败时,返回EOF。 308 | 309 | 下面的例子以追加模式打开文件用来写入,将给定的字符串写入相关的流中,然后关闭流: 310 | \begin{lstlisting} 311 | stream = fopen ("journal.txt", "a"); 312 | if (!stream) 313 | /* error */ 314 | if (fputs ("The ship is made of wood.\n", stream) == EOF) 315 | /* error */ 316 | if (fclose (stream) == EOF) 317 | /* error */ 318 | \end{lstlisting} 319 | 320 | 321 | \subsection{写入二进制数据} 322 | 323 | 如果程序需要写入二进制数据,则单独字符和行并不能满足需求。为了直接存储二进制数据例如C变量,标准I/O提供了fwrite()函数: 324 | \begin{lstlisting} 325 | #include 326 | size_t fwrite (void *buf, 327 | size_t size, 328 | size_t nr, 329 | FILE *stream); 330 | \end{lstlisting} 331 | 332 | 调用fwrite()会把buf指向的nr个元素写入到stream中,每个元素长为size。文件指针会向前移动写入的所有字节的长度。 333 | 334 | 成功时,会返回写入元素的个数(不是字节的个数!)。返回小于nr的数表明发生了错误。 335 | 336 | \subsection{缓冲I/O示例程序} 337 | 338 | 现在让我们看一个例子-实际上是一个完整的程序-它综合了本章之前涉及到的许多函数。这个程序首先定义了一个结构pirate,然后声明了两个这个类型的变量。程序初始化了其中的一个变量,随后通过一个指向文件data的输出流将它写入磁盘中。通过一个不同的流,程序直接从data中读取数据存储到pirate结构的另一个实例中。最后程序把这个结构的内容输出到标准输出: 339 | \begin{lstlisting} 340 | #include 341 | int main (void) 342 | { 343 | FILE *in, *out; 344 | struct pirate 345 | { 346 | char name[100]; /* real name */ 347 | unsigned long booty; /* in pounds sterling */ 348 | unsigned int beard_len; /* in inches */ 349 | } p, blackbeard = { "Edward Teach", 950, 48 }; 350 | 351 | out = fopen ("data", "w"); 352 | if (!out) 353 | { 354 | perror ("fopen"); 355 | return 1; 356 | } 357 | if (!fwrite (&blackbeard, sizeof (struct pirate), 1, out)) 358 | { 359 | perror ("fwrite"); 360 | return 1; 361 | } 362 | if (fclose (out)) 363 | { 364 | perror ("fclose"); 365 | return 1; 366 | } 367 | in = fopen ("data", "r"); 368 | if (!in) 369 | { 370 | perror ("fopen"); 371 | return 1; 372 | } 373 | if (!fread (&p, sizeof (struct pirate), 1, in)) 374 | { 375 | perror ("fread"); 376 | return 1; 377 | } 378 | if (fclose (in)) 379 | { 380 | perror ("fclose"); 381 | return 1; 382 | } 383 | printf ("name=\"%s\" booty=%lu beard_len=%u\n", 384 | p.name, p.booty, p.beard_len); 385 | return 0; 386 | } 387 | \end{lstlisting} 388 | 389 | 390 | 输出结果当然是原来的值: 391 | \begin{verbatim} 392 | name="Edward Teach" booty=950 beard_len=48 393 | \end{verbatim} 394 | 395 | 我们需要牢记的是,因为变量长度、对齐等等的不同,一个程序写入的二进制数据对另外一个程序可能是不可读的。就是说,不同的程序-即使是不同机器上的同一个程序-可能不能正确地读取fwrite()写入的数据。在我们的例子中,可以想象一下如果无符号长整型的大小改变了,或者填充的数量改变了,将会是什么情况。这些东西只能在拥有特定ABI的特定机型上才能保证相同。 396 | 397 | \section{定位流} 398 | 399 | 通常,控制当前流的位置是很有用的。可能程序正在读取一个复杂的基于记录的文件,而且需要跳转。必要的时候,流可能需要将设置为文件的初始位置。不管什么情况,标准I/O提供了一系列功能等价于系统调用lseek()的函数(第二章中讨论过)。fseek()函数,标准I/O最常用的定位函数,操纵流指向文件中由offset和whence指定的位置: 400 | \begin{lstlisting} 401 | #include 402 | int fseek (FILE *stream, long offset, int whence); 403 | \end{lstlisting} 404 | 405 | 如果whence被设置为SEEK\_SET,文件的位置被设置到offset处。如果whence被设置为SEEK\_CUR,文件位置被设置到当前位置加上offset.如果whence被设置为SEEK\_END,文件位置被设置到文件末尾加上offset。 406 | 407 | 成功时,fseek()返回0,清空文件结束标志,并且取消ungetc()操作。错误时,它返回-1,并且相应的设置errno。最常见的错误有非法流(EBADF)和非法whence参数(EINVAL)。另外,标准I/O还提供了fsetpos()函数: 408 | \begin{lstlisting} 409 | #include 410 | int fsetpos (FILE *stream, fpos_t *pos); 411 | \end{lstlisting} 412 | 413 | 这个函数将流的位置设置到pos处。它和将whence设置为SEEK\_SET时的fseek()功能一致。成功时它返回0。否则,返回-1,并且相应地设置errno的值。这个函数(和将要学到的对应的fgetpos()函数)只在其它(非UNIX)能够用复杂数据类型表示流的位置的平台上提供。在这些平台上,这个函数是唯一能够将流位置设置为任意值的方法,因为C的长整型可能不够大。linux的程序一般不使用这个接口,除非它们希望能够被移植到所有的平台上。 414 | 415 | 标准I/O也提供了rewind()函数,下面是一个片段: 416 | \begin{lstlisting} 417 | #include 418 | void rewind (FILE *stream);、 419 | \end{lstlisting} 420 | 421 | 该调用: 422 | \begin{lstlisting} 423 | rewind(stream); 424 | \end{lstlisting} 425 | 426 | 将位置重置到流的初始位置。它等价于: 427 | \begin{lstlisting} 428 | fseek (stream, 0, SEEK_SET); 429 | \end{lstlisting} 430 | 431 | 此外,它还清空错误标记。注意rewind()没有返回值,因此不能够直接提供错误信息。调用函数如果希望获取错误,需要在调用之前清空errno,并且检查这个变量在调用之后是否非零。例如: 432 | \begin{lstlisting} 433 | errno = 0; 434 | rewind (stream); 435 | if (errno) 436 | /* error */ 437 | \end{lstlisting} 438 | 439 | 440 | \subsection{获得当前流位置} 441 | 442 | 和lseek()不同,fseek()不返回更新后的位置。一个单独的接口提供了这个功能。ftell()函数返回当前流的位置: 443 | \begin{lstlisting} 444 | #include 445 | long ftell (FILE *stream); 446 | \end{lstlisting} 447 | 448 | 错误时,它返回-1,并且相应的设置errno。选择性的,标准输入输出提供了fgetpos()函数: 449 | \begin{lstlisting} 450 | #include 451 | int fgetpos (FILE *stream, fpos_t *pos); 452 | \end{lstlisting} 453 | 454 | 成功时,fgetpos()返回0,并且将当前流的位置设置为pos。失败时,返回-1,并且相应的设置errno。和fsetpos()一样,fgetpos()只在有复杂文件位置类型的非linux平台上提供。 455 | 456 | \section{清洗一个流} 457 | 458 | 标准I/O库提供了一个用来将用户缓冲区写入内核,并且保证所有的数据都通过write()写出的函数。fflush()函数提供了这一功能: 459 | \begin{lstlisting} 460 | #include 461 | int fflush (FILE *stream); 462 | \end{lstlisting} 463 | 464 | 调用该函数时,stream指向的流中的所有未写入的数据会被清洗(flush)到内核中。如果stream是空的(NULL ),所有进程打开的流会被清洗掉。成功时fflush()返回0。失败时,它返回EOF,并且相应的设置errno。 465 | 466 | 为了理解fflush()函数的作用,你必须理解C函数库维持的缓冲区和内核自己拥有的缓冲区的区别。本章提到的所有调用的缓冲区都是通过 C函数库来维护的,它们保留在用户空间中,而不是内核空间。这就是效率提高的原因-程序保留在用户空间中,并且运行用户的代码,不执行系统调用。只有当磁盘或其它介质必须被访问时系统调用才会被执行。 fflush()只是把用户缓冲的数据写入到内核缓冲区。效果和没有用户缓冲区一样,而且write()是被直接调用的。这并不保证数据能够写入物理介质-如果需要的话,使用fsync()这一类函数(见第二章同时I/O)。更多的情况是在调用fflush()后, 立即调用fsync(): 就是说先保证用户缓冲区被写入到内核,然后保证内核缓冲区被写入到磁盘。 467 | 468 | \section{错误和文件结束} 469 | 470 | 一些标准I/O接口,例如fread(), 向调用者传递失败信息的能力很差,因为它们没有提供区分错误和EOF的机制。在一些场合中调用这些函数时,需要区分给定的流出现了错误还是到达了文件结尾。标准I/O为此提供了两个函数。函数ferror()测试是否在流上设置了错误标志: 471 | \begin{lstlisting} 472 | #include 473 | int ferror (FILE *stream); 474 | \end{lstlisting} 475 | 476 | 错误标志由其它响应错误的标准I/O函数设置。如果标志被设置,函数返回非零值,否则返回0。函数feof()测试文件结尾标志是否被设置: 477 | \begin{lstlisting} 478 | #include 479 | int feof (FILE *stream); 480 | \end{lstlisting} 481 | 482 | 当到达文件的结尾时,EOF标志会被其它标准I/O函数设置。如果标志被设置了,函数返回非零值,否则返回0。 clearerr()函数为流清空错误和文件结尾标志: 483 | \begin{lstlisting} 484 | #include 485 | void clearerr (FILE *stream); 486 | \end{lstlisting} 487 | 488 | 它没有返回值,而且不会失败(没有方法知道是否提供了一个非法的流)。只有在检查error和EOF标志之后,你才可以调用clearerr(),因为这些操作是不可恢复的。例如: 489 | \begin{lstlisting} 490 | /* 'f' is a valid stream */ 491 | if (ferror (f)) 492 | printf ("Error on f!\n"); 493 | if (feof (f)) 494 | printf ("EOF on f!\n"); 495 | clearerr (f); 496 | \end{lstlisting} 497 | 498 | 499 | \section{获得关联的文件描述符} 500 | 501 | 有时候,从流中获得文件描述符是很方便的。例如,当一个关联的标准I/O函数不存在时,可以通过流的文件描述符对一个流执行系统调用。为了获得流的文件描述符,可以使用fileno(): 502 | \begin{lstlisting} 503 | #include 504 | int fileno (FILE *stream); 505 | \end{lstlisting} 506 | 507 | 成功时,fileno()返回和流相关联的文件描述符。失败时,它返回-1。只有当给定的流非法时才可能发生这种清况,这时候函数会将errno设置为EBADF。通常不建议混合使用标准输入输出调用和系统调用。使用fileno()时程序员需要确保操作非常谨慎。尤其需要注意的是,最好在执行获取文件描述符之前对流进行冲洗(flush)。记住,最好永远不要混合使用I/O操作。 508 | 509 | \section{控制缓冲} 510 | 511 | 标准I/O实现了三种用户缓冲,而且为开发者提供了一个用来控制缓冲区大小和类型的接口。不同的用户缓冲提供不同功能,并适用于不同的场合。下面是一些选项: 512 | \begin{list}{} 513 | \item \textbf{不缓冲} 514 | 515 | 没有执行用户缓冲。数据直接提交到内核。因为这和用户缓冲对立,这个选项通常不用。标准错误默认是不缓冲的。 516 | 517 | \item \textbf{行缓冲} 518 | 519 | 缓冲以行为单位执行。每当遇到换行符,缓冲区被提交到内核。行缓冲对输出到屏幕的流有用。因此,它是终端的默认缓冲方式(标准输出默认为行缓冲)。 520 | 521 | \item \textbf{块缓冲} 522 | 523 | 缓冲以块为单位执行。这是本章一开始讨论的缓冲类型,而且它适用于文件。默认的所有和文件相关的流都是块缓冲的。标准I/O称块缓冲为全缓冲。 524 | \end{list} 525 | 526 | 527 | 528 | 大部分情况下,默认的缓冲类型是最高效的。然而,标准I/O确实提供了一个用来控制使用的缓冲类型的函数: 529 | \begin{lstlisting} 530 | #include 531 | int setvbuf (FILE *stream, char *buf, int mode, size_t size); 532 | \end{lstlisting} 533 | 534 | setbuf()函数设置流的缓冲类型模式,模式必须是以下的一种: 535 | 536 | 537 | \begin{eqlist*} 538 | \item[\textbf{\_IONBF}] 无缓冲 539 | \item[\textbf{\_IOLBF}] 行缓冲 540 | \item[\textbf{\_IOFBF}] 块缓冲 541 | \end{eqlist*} 542 | 543 | 544 | 545 | 546 | 除了\_IONBF情况下buf和size被忽略了,buf可以指向一个size字节大小的缓冲空间,标准I/O会用它来执行对给定流的缓冲。如果buf为空, 缓冲区则由glibc自动分配。 547 | 548 | setvbuf()函数必须在打开流后,但在执行任何操作之前被调用。 成功时它返回0,出错则返回一个非零值。 549 | 550 | 在流关闭时供其使用的缓冲区必须存在。一个常见的错误是把缓冲区定义成作用域中的自动变量,并且作用域结束之前没有关闭流。特别应该注意的是不要使用一个main()函数内的缓冲区,且没有显式地关闭流。例如,以下代码中有一个错误: 551 | \begin{lstlisting} 552 | #include 553 | int main (void) 554 | { 555 | char buf[BUFSIZ]; 556 | /* set stdin to block-buffered with a BUFSIZ buffer */ 557 | setvbuf (stdout, buf, _IOFBF, BUFSIZ); 558 | printf ("Arrr!\n"); 559 | return 0; 560 | } 561 | \end{lstlisting} 562 | 563 | 564 | 这个错误可以通过在离开作用域之前显式地关闭流或将流作为全局变量来修正。 565 | 566 | 总的来说,开发者不用操心在流上的缓冲。除了标准错误外,终端是行缓冲的,而且这样就够了。文件是块缓冲的,这样也就可以了。默认的块缓冲区大小是在中定义的BUFSIZ,而且通常情况下这是最优的选择(一个标准块大小的数个整数倍)。 567 | 568 | \section{线程安全} 569 | 570 | 线程就是在同一个进程中执行的多个实例。线程的定义是共享同一地址空间的多个进程。如果不采取数据同步措施或将数据线程私有化,线程可以任何时间修改共享数据。支持线程的操作系统提供加锁机制(保证相互排斥的程序结构)来保证线程不会互相干扰。标准I/O使用这些机制。而且,这些机制通常还不能满足需求。例如,有时候你想给一组调用加锁,将临界区(一段独立运行的代码)的范围从一个I/O操作扩大到几个。而有些情况下,你可能想取消锁机制来提高效率。本节中,我们会讨论怎样做到这两点。\footnote[1]{通常,取消锁会导致各种各样的问题。但一些程序可能显式地将所有的I/O操作都由一个线程来完成。在这种情况下,没有必要增加锁的开销。} 571 | 572 | 标准I/O的函数本质上是线程安全的。在内部实现中,设置了一把锁,一个锁计数器,和为每个打开的流创建的所有者线程。一个线程要想执行任何I/O请求,必须首先获得锁而且成为所有者线程。两个或多个运行在同一流上的线程不能交错地执行I/O操作,因此,在单独一个函数调用的上下文中,标准I/O操作是原子的。 573 | 574 | 当然在实际应用中,许多应用程序需要比单独的函数调用更强的原子性。例如,如果多个线程正在执行写入请求,应用程序可能希望这些读写请求没有间断地完成。为了达到这个目的,标准I/O为独立操纵和流关联的锁提供了一系列的函数。 575 | 576 | 577 | \subsection{手动文件加锁} 578 | 579 | 函数flockfile()会等待流被解锁,然后获得锁,增加锁计数,成为流的所有者线程,然后返回: 580 | \begin{lstlisting} 581 | #include 582 | void flockfile (FILE *stream); 583 | \end{lstlisting} 584 | 585 | 函数funlockfile() 减少与流相关的锁计数: 586 | \begin{lstlisting} 587 | #include 588 | void funlockfile (FILE *stream); 589 | \end{lstlisting} 590 | 591 | 如果锁计数器达到了0,当前的线程放弃流的所有权,另一个线程现在能够获得锁。这些调用可以嵌套。就是说,一个线程可以执行多个flockfile()调用,而流在程序执行相同数量的funlockfile()调用前不会解锁。 ftrylockfile()是flockfile()的非堵塞版本: 592 | \begin{lstlisting} 593 | #include 594 | int ftrylockfile (FILE *stream); 595 | \end{lstlisting} 596 | 597 | 如果流当前加了锁,ftrylockfile()不做任何处理,并立即返回一个非零值。如果流当前没有加锁,它获得锁,增加锁计数,成为流的所有者线程,并且返回0。让我们看一个例子: 598 | \begin{lstlisting} 599 | flockfile (stream); 600 | fputs ("List of treasure:\n", stream); 601 | fputs (" (1) 500 gold coins\n", stream); 602 | fputs (" (2) Wonderfully ornate dishware\n", stream); 603 | funlockfile (stream); 604 | \end{lstlisting} 605 | 606 | 尽管单独的fputs()操作不会产生竞争-例如,我们永远不会有内容打断"List oftreasure"的输出,另一个线程可能会夹杂在当前线程的两个fputs()语句之间。理想情况下,一个应用程序的多个线程不应该向同一个流提交 I/O操作。然而如果你的程序不需要这么做,并且你需要一个比单独函数调用更大的原子操作区域,flockfile()和它的相关函数可以解决这个问题。 607 | 608 | \subsection{不加锁流操作} 609 | 610 | 手动给流加锁还有另外一个原因。只有应用开发者才能提供更精细和更准确的控制锁,可以将加锁的代价降到最小,并提高执行效率。为此,Linux提供了一系列的函数,类似于通常的标准I/O接口,但是不执行任何锁操作。它们实际上是不加锁的标准I/O: 611 | \begin{lstlisting} 612 | #define _GNU_SOURCE 613 | #include 614 | int fgetc_unlocked (FILE *stream); 615 | char *fgets_unlocked (char *str, int size, FILE *stream); 616 | size_t fread_unlocked (void *buf, size_t size, size_t nr,FILE *stream); 617 | int fputc_unlocked (int c, FILE *stream); 618 | int fputs_unlocked (const char *str, FILE *stream); 619 | size_t fwrite_unlocked (void *buf, size_t size, size_t nr,FILE *stream); 620 | int fflush_unlocked (FILE *stream); 621 | int feof_unlocked (FILE *stream); 622 | int ferror_unlocked (FILE *stream); 623 | int fileno_unlocked (FILE *stream); 624 | void clearerr_unlocked (FILE *stream); 625 | \end{lstlisting} 626 | 627 | 除了它们不检查或获得指定流上的锁,这些函数与相对的加锁函数执行相同操作。如果需要锁机制,程序员有责任保证手工获得并且释放锁。尽管POSIX定义了一些不加锁的标准I/O函数,但上面的函数没有一个是POSIX定义的。它们都是Linux特有的,许多其它的Unix系统部分的支持以上提到的函数。 628 | 629 | \section{对标准I/O的批评} 630 | 631 | 尽管标准I/O广泛使用,一些专家还是指出了它的一些缺点。一些函数,例如fgets(), 有时候不能够满足要求。其它函数,例如gets(),太不安全,就差被逐出标准了。 632 | 633 | 对标准I/O最大的抱怨是双副本的性能影响。当读取数据时,标准I/O对内核执行read()系统调用,从内核中复制数据到标准I/O缓冲区。然后当一个程序通过标准I/O执行一个读请求时-例如,用fgetc()-数据又被复制,这一次从标准I/O的缓冲区到指定的缓冲区。写入请求时用相反的方式运行:数据先从给定的缓冲空间复制到标准I/O缓冲区,然后又从标准I/O缓冲区通过write()写入内核。 634 | 635 | 一个解决的办法是,通过让每个读请求返回一个指向标准I/O缓冲区的指针来避免双复本。数据可以被直接从标准I/O缓冲区中读取,不需要多余的复制。当程序确实需要自己本地缓冲区的数据时-可能向其中写数据-总可以手动地执行复制。这个实现需要提供了一个"释放"的接口,允许程序当它们完成缓冲区的一块读取时发出信号。 636 | 637 | 写操作会更复杂些,但是仍然能够被避免双复本。当执行一个写入请求时,这个实现会记录指针位置,最终当准备好将数据冲洗到内核时再写出数据。这些可以通过分散-聚集I/O(scatter-gather I/O)中的writev()函数来实现,完成这个功能只需要一个系统调用。(我们会在下一章讨论散布-聚集I/O)。 638 | 639 | 现在有一些高度优化的用户缓冲库,它们用了类似于我们刚刚讨论的方法来解决双复本问题。一些开发者会选择实现他们自己的用户缓冲方案。但是尽管有不同的选择,标准I/O仍然很流行。 640 | 641 | \section{结论} 642 | 643 | 标准I/O是C标准库提供的一个用户缓冲库。除掉一些不完善的地方,它是一个很强大而且非常流行的解决方案。许多C程序员,实际上除了标准I/O,对其它的方案几乎一无所知。当然,对于终端I/O,行缓冲是最理想的,标准I/O是它的唯一的解决方法。又有谁直接调用write()向标准输出写过数据呢? 644 | 645 | 标准I/O(仅从这点来看,也包括用户缓冲)适用于下列情况: 646 | 647 | \begin{itemize} 648 | \item 你可能需要执行许多系统调用,而你希望通过合并这些调用从而尽量减少开销。 649 | \item 在性能至关重要的场合,你希望保证所有的I/O以块大小进行,并且能保持块对齐。 650 | \item 你的访问模式是基于字符或行的,你希望通过一个接口来实现这种访问,但又不想进行太多的系统调用。 651 | \item 相比底层的Linux系统调用,你更喜欢高层次的接口。 652 | \end{itemize} 653 | 654 | 然而最大的灵活在于你能够直接的使用Linux系统调用。下一章,我们将学习高级形式的I/O和相关的系统调用。 655 | -------------------------------------------------------------------------------- /body/Ch4.log: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cliffwoo/LSP_CN/aa76748ec4a9e96a0da20a3dd046e557b0a5bd50/body/Ch4.log -------------------------------------------------------------------------------- /body/Ch6.log: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cliffwoo/LSP_CN/aa76748ec4a9e96a0da20a3dd046e557b0a5bd50/body/Ch6.log -------------------------------------------------------------------------------- /body/Copyright.tex: -------------------------------------------------------------------------------- 1 | \chapter{版权声明} 2 | 《Linux System Programming》中文版的翻译工作为哈尔滨工业大学计算机学院IBM俱乐部的练习项目。译文仅供系统编程的学习和交流使用,严禁在公共领域传播或用于商业用途。 3 | 4 | 《Linux System Programming》的版权归作者及原出版社所有,译文仅供系统编程的学习和交流使用。未经原书作者及出版社允许的出版、发行、制作所引发的纠纷,由当事人负责,特此声明。 5 | 6 | \begin{flushright} 7 | \today 8 | \end{flushright} 9 | -------------------------------------------------------------------------------- /body/Preface.tex: -------------------------------------------------------------------------------- 1 | %\newcommand{\chuhao}{\fontsize{42pt}{\baselineskip}\selectfont} 2 | %\newcommand{\xiaochuhao}{\fontsize{36pt}{\baselineskip}\selectfont} 3 | %\newcommand{\xiaoerhao}{\fontsize{18pt}{\baselineskip}\selectfont} 4 | %\newcommand{\xiaosihao}{\fontsize{12pt}{\baselineskip}\selectfont} 5 | %\newcommand{\xiaowuhao}{\fontsize{9pt}{\baselineskip}\selectfont} 6 | \vspace*{16ex} 7 | \begin{center} 8 | \textit{\huge 谨将我们的工作献给} 9 | \end{center} 10 | 11 | \begin{center} 12 | \textit{\Large 即将毕业离校的兄弟们} --- \textit{\Large 林晓鑫、刘德超、黄巍、周蓝珺、胡禹轩、王新喜、何春晓、崔剑、李浩。} 13 | \end{center} 14 | 15 | \begin{center} 16 | \textit{\large 以及} 17 | \end{center} 18 | 19 | \begin{center} 20 | \textit{\Large 潘海东即将出世的小Baby!} 21 | \end{center} 22 | 23 | \newpage 24 | \chapter{译者序} 25 | 《Linux System Programming》(简称LSP)的中文翻译工作是浮图开放实验室和哈尔滨工业大学计算机学院IBM俱乐部 《深入理解计算机系统》讨论班的练习项目。参与翻译工作的同学包括从本科二年级到研究生二年级的十一位同学。他们是林晓鑫、王澍、崔玉春、吉飞飞、何春晓、熊飞、李志、张祖羽、张智、陈盛、张永辉。附录的翻译由SMS@lilacbbs.com完成,参考文献部分的翻译由王澍完成。刘文懋、王耀、刘德超、于墨、王新喜等同学参与了审校工作。全书的初稿审校由吴晋完成。本书基于哈尔滨工业大学硕士博士论文TeX模板制作,全书的模板修正工作由李志完成。 26 | 27 | 本书的翻译工作基于LSP第一版完成,并根据英文版勘误进行了修正。 28 | 29 | 在本书内部审核版本发布后得到了原IBM俱乐部成员谢煜波(现供职于微软亚洲工程院)和戴晓光(现供职于SUN中国有限公司)的大力支持,他们利用宝贵的业余时间对部分章节进行了仔细的审校,并提出了大量细致的修改意见。他们的修改意见使所有参与翻译的同学受益良多。在此向他们表示感谢。 30 | 31 | 在翻译过程中还得到了紫丁香社区和Harbin Linux User Group网友的大力支持,在此向他们一并表示感谢。 32 | 33 | 由于译者在系统编程方面并没有丰富的经验,整个翻译工作以学习为目的,因此书中的错误和疏漏在所难免。如果书中存在任何问题,请用如下方式和我们联系: 34 | \begin{center} 35 | \begin{description} 36 | % \item[Website]: 37 | % \begin{enumerate} 38 | \item[Website]: http://www.footoo.org 39 | % \item http://sites.google.com/a/footoo.org/footoo-lab/ 40 | % \end{enumerate} 41 | \item[Twitter]: http://twitter.com/cliffwoo 42 | \item[Email]:\mbox{cliffwoo@gmail.com} 或者 \mbox{cliffwoo@footoo.org} 43 | \item[Google Groups]:http://groups.google.com/group/lspcn/ 44 | \end{description} 45 | \end{center} 46 | \begin{flushright} 47 | 吴晋 于 哈尔滨工业大学\linebreak[2] 48 | 49 | 2009年4月30日 50 | \end{flushright} 51 | -------------------------------------------------------------------------------- /body/iconv.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | #=============================================================================== 3 | # 4 | # FILE: iconv.sh 5 | # 6 | # USAGE: ./iconv.sh 7 | # 8 | # DESCRIPTION: convert utf8 to gbk 9 | # 10 | # OPTIONS: --- 11 | # REQUIREMENTS: --- 12 | # BUGS: --- 13 | # NOTES: --- 14 | # AUTHOR: (), 15 | # COMPANY: 16 | # VERSION: 1.0 17 | # CREATED: 12/10/2008 03:40:55 PM CST 18 | # REVISION: --- 19 | #=============================================================================== 20 | cp Ch4.tex t.tex 21 | iconv -f utf8 -t gbk -o Ch4gbk.tex Ch4.tex 22 | mv Ch4gbk.tex Ch4.tex 23 | -------------------------------------------------------------------------------- /chinesebst.bst: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cliffwoo/LSP_CN/aa76748ec4a9e96a0da20a3dd046e557b0a5bd50/chinesebst.bst -------------------------------------------------------------------------------- /chinesebst_GBK_xelatex.bst: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cliffwoo/LSP_CN/aa76748ec4a9e96a0da20a3dd046e557b0a5bd50/chinesebst_GBK_xelatex.bst -------------------------------------------------------------------------------- /figures/ch4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cliffwoo/LSP_CN/aa76748ec4a9e96a0da20a3dd046e557b0a5bd50/figures/ch4.jpg -------------------------------------------------------------------------------- /figures/ch5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cliffwoo/LSP_CN/aa76748ec4a9e96a0da20a3dd046e557b0a5bd50/figures/ch5.jpg -------------------------------------------------------------------------------- /figures/golfer.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cliffwoo/LSP_CN/aa76748ec4a9e96a0da20a3dd046e557b0a5bd50/figures/golfer.pdf -------------------------------------------------------------------------------- /figures/hit_logo.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cliffwoo/LSP_CN/aa76748ec4a9e96a0da20a3dd046e557b0a5bd50/figures/hit_logo.pdf -------------------------------------------------------------------------------- /figures/lspcover1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cliffwoo/LSP_CN/aa76748ec4a9e96a0da20a3dd046e557b0a5bd50/figures/lspcover1.jpg -------------------------------------------------------------------------------- /figures/paipai.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cliffwoo/LSP_CN/aa76748ec4a9e96a0da20a3dd046e557b0a5bd50/figures/paipai.png -------------------------------------------------------------------------------- /figures/title.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cliffwoo/LSP_CN/aa76748ec4a9e96a0da20a3dd046e557b0a5bd50/figures/title.JPG -------------------------------------------------------------------------------- /figures/title_l.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cliffwoo/LSP_CN/aa76748ec4a9e96a0da20a3dd046e557b0a5bd50/figures/title_l.jpg -------------------------------------------------------------------------------- /figures/title_r.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cliffwoo/LSP_CN/aa76748ec4a9e96a0da20a3dd046e557b0a5bd50/figures/title_r.jpg -------------------------------------------------------------------------------- /fixbbl.txt: -------------------------------------------------------------------------------- 1 | \XeTeXinputencoding "gbk" 2 | -------------------------------------------------------------------------------- /floatflt.sty: -------------------------------------------------------------------------------- 1 | %% 2 | %% This is file `floatflt.sty', 3 | %% generated with the docstrip utility. 4 | %% 5 | %% The original source files were: 6 | %% 7 | %% floatflt.dtx (with options: `paketkod') 8 | %% 9 | %% Copyright (c) 1994-1998 by Mats Dahlgren . 10 | %% All rights reserved. See the file `floatflt.ins' for information 11 | %% on how you may (re-)distribute the `floatflt' package files. 12 | %% You are not allowed to make any changes to this file without 13 | %% explicit permission from the author. 14 | %% 15 | \NeedsTeXFormat{LaTeX2e}[1996/12/01] 16 | \ProvidesPackage{floatflt}[1997/07/16 v. 1.31] 17 | \newcounter{OptionTest} 18 | \setcounter{OptionTest}{0} 19 | \DeclareOption{rflt}{\setcounter{OptionTest}{1}} 20 | \DeclareOption{lflt}{\setcounter{OptionTest}{2}} 21 | \DeclareOption{vflt}{\setcounter{OptionTest}{0}} 22 | \DeclareOption*{\OptionNotUsed} 23 | \ProcessOptions 24 | \newbox\figbox 25 | \newbox\tabbox 26 | \newbox\pagebox 27 | \newcount\ffigcount 28 | \newcount\ftabcount 29 | \newcount\fftest 30 | \newcount\hangcount 31 | \newcount\nosuccesstryfig 32 | \newcount\nosuccesstrytab 33 | \newdimen\figgutter \figgutter=1truepc 34 | \newdimen\tabgutter \tabgutter=1truepc 35 | \newdimen\htdone \htdone=0pt 36 | \newdimen\pageht 37 | \newdimen\startpageht 38 | \newdimen\tabbredd 39 | \newdimen\floatfltwidth 40 | \newdimen\fltitemwidth 41 | \newif\iftryingfig \tryingfigfalse 42 | \newif\iftryingtab \tryingtabfalse 43 | \newif\ifdoingfig \doingfigfalse 44 | \newif\ifdoingtab \doingtabfalse 45 | \newif\iffigprocessing \figprocessingfalse 46 | \newif\iftabprocessing \tabprocessingfalse 47 | \newif\ifpageafterfig \pageafterfigfalse 48 | \newif\ifpageaftertab \pageaftertabfalse 49 | \newif\ifoddpages 50 | \newif\ifoutput 51 | \newtoks\outputpretest 52 | \newenvironment{floatingfigure}[2][v]% 53 | {\@tfor \@tempa :=#1\do 54 | {\if\@tempa r\global\oddpagestrue\fi 55 | \if\@tempa l\global\oddpagesfalse\fi 56 | \if\@tempa p% 57 | \ifodd\c@page\global\oddpagestrue 58 | \else\global\oddpagesfalse\fi 59 | \fi 60 | \if\@tempa v% 61 | \ifnum\theOptionTest=0 62 | \ifodd\c@page\global\oddpagestrue 63 | \else\global\oddpagesfalse\fi 64 | \else 65 | \ifodd\theOptionTest\global\oddpagestrue 66 | \else\global\oddpagesfalse\fi 67 | \fi 68 | \fi 69 | } 70 | \expandafter\ifx\csname oldoutput\endcsname\relax% ref. TeXbook Ex.7.7 71 | \PackageError{floatflt}{The `floatflt' package is not initialized} 72 | {Try to reinstall the `floatflt' package.\MessageBreak 73 | Type `x' to quit or to try to go on.}\@@end\fi 74 | \global\everypar={\tryfig\oldeverypar}% must be set globally! 75 | \global\advance\ffigcount by 1 76 | \iffigprocessing 77 | {\count0=\ffigcount\advance\count0 by -1 78 | \PackageWarningNoLine{floatflt}{Floating figures \the\count0\space% 79 | \space and \the\ffigcount\space colliding}% 80 | }% 81 | \fi 82 | \iftabprocessing \PackageWarningNoLine{floatflt}{Floating figure % 83 | \the\ffigcount\space and floating table \the\ftabcount\space colliding} 84 | \fi 85 | \def\@captype{figure} 86 | \global\setlength{\floatfltwidth}{#2} 87 | \global\figprocessingtrue 88 | \global\setbox\figbox=\vbox\bgroup% begin of figbox 89 | \hrule height 0pt width #2 depth 0pt% 90 | \hsize=#2% 91 | } 92 | { 93 | \egroup 94 | \figinsert\par% 95 | } 96 | \newenvironment{floatingtable}[2][v]% 97 | {\@tfor \@tempa :=#1\do 98 | {\if\@tempa r\global\oddpagestrue\fi 99 | \if\@tempa l\global\oddpagesfalse\fi 100 | \if\@tempa p% 101 | \ifodd\c@page\global\oddpagestrue 102 | \else\global\oddpagesfalse\fi 103 | \fi 104 | \if\@tempa v% 105 | \ifnum \theOptionTest=0 106 | \ifodd\c@page\global\oddpagestrue 107 | \else\global\oddpagesfalse\fi 108 | \else 109 | \ifodd\theOptionTest\global\oddpagestrue 110 | \else\global\oddpagesfalse\fi 111 | \fi 112 | \fi 113 | } 114 | \expandafter\ifx\csname oldoutput\endcsname\relax% ref. TeXbook Ex.7.7 115 | \PackageError{floatflt}{The `floatflt' package is not initialized} 116 | {Try to reinstall the `floatflt' package.\MessageBreak 117 | Type `x' to quit or to try to go on.}\@@end\fi 118 | \global\setbox\tabbox=\vbox\bgroup\hrule height 0pt width 0pt depth 0pt% 119 | \hsize=0pt\egroup 120 | \global\everypar={\trytab\oldeverypar} 121 | \global\advance\ftabcount by 1 122 | \iftabprocessing 123 | {\count0=\ftabcount\advance\count0 by -1 124 | \PackageWarningNoLine{floatflt}{Floating tables \the\count0\space% 125 | \space and \the\ftabcount \space colliding}% 126 | } 127 | \fi 128 | \iftabprocessing \PackageWarningNoLine{floatflt}{Floating table % 129 | \the\ffigcount\space and floating figure \the\ftabcount\space colliding} 130 | \fi 131 | \settowidth{\tabbredd}{#2} 132 | \global\setlength{\floatfltwidth}{\tabbredd} 133 | \def\@captype{table} 134 | \global\tabprocessingtrue 135 | \global\setbox\tabbox=\vbox\bgroup% begin of tabbox 136 | \hrule height 0pt width\tabbredd depth 0pt% 137 | \hsize=\tabbredd 138 | \noindent\ifnum\ftabcount >1\ifoddpages\else\hspace*{-12pt}\fi\fi% 139 | #2\vspace{0.2\baselineskip}% 140 | } 141 | { 142 | \egroup% end of \tabbox 143 | \tabinsert\par% 144 | } 145 | \AtBeginDocument{% 146 | \edef\oldoutput{\the\output}% 147 | \output={\the\outputpretest% 148 | \ifoutput\oldoutput\fi} 149 | \outputpretest={\outputtrue} 150 | \edef\oldeverypar{\the\everypar} 151 | } 152 | \def\dofigtest{% 153 | \ifnum\outputpenalty=-10005 154 | \setbox\pagebox=\vbox{\unvbox255}% 155 | \global\pageht=\ht\pagebox 156 | \global\outputfalse 157 | \unvbox\pagebox 158 | \else 159 | \global\outputtrue 160 | \ifdoingfig 161 | \global\pageafterfigtrue 162 | \fi 163 | \fi}% 164 | \def\dotabtest{% 165 | \ifnum\outputpenalty=-10005 166 | \setbox\pagebox=\vbox{\unvbox255}% 167 | \global\pageht=\ht\pagebox 168 | \global\outputfalse 169 | \unvbox\pagebox 170 | \else 171 | \global\outputtrue 172 | \ifdoingtab 173 | \global\pageaftertabtrue 174 | \fi 175 | \fi}% 176 | \def\tryfig{% 177 | \iftryingfig 178 | {\everypar={\relax}\setbox0=\lastbox% 179 | \parindent=\wd0 \parskip=0pt \par% 180 | \penalty-10005 \leavevmode}% 181 | \dimen0=\vsize% 182 | \advance\dimen0 by -\pageht% 183 | \advance\dimen0 by -2\baselineskip% 184 | \ifdim\dimen0>\ht\figbox% 185 | \dimen0=0.3\baselineskip 186 | \vrule depth \dimen0 width 0pt 187 | \vadjust{\kern -\dimen0% 188 | \vtop to \dimen0{% 189 | \baselineskip=\dimen0% 190 | \vss \vbox to 1ex{% 191 | \ifoddpages% 192 | \hbox to \hsize{\hss\copy\figbox}% 193 | \else% leftsetting 194 | \hbox to \hsize{\copy\figbox\hss}% 195 | \fi% \ifodd\count0 196 | \vss}\null}}% 197 | \global\tryingfigfalse% 198 | \global\doingfigtrue 199 | \global\startpageht=\pageht 200 | \global\htdone=0pt 201 | \dohangf 202 | \ifnum\nosuccesstryfig>0% 203 | \typeout{floatflt Message: Flt. fig. \the\ffigcount\space set on page 204 | \the\count0, shifted \the\nosuccesstryfig\space par(s) forward.}% 205 | \else 206 | \typeout{Package floatflt Message: Floating figure \the\ffigcount 207 | \space set on page \the\count0}% 208 | \fi 209 | \else 210 | \global\advance\nosuccesstryfig by 1 211 | \fi 212 | \else% 213 | \ifdoingfig 214 | {\everypar={\relax}\setbox0=\lastbox 215 | \parindent=\wd0 \parskip=0pt \par 216 | \penalty-10005 \leavevmode}% 217 | \global\htdone=\pageht 218 | \global\advance\htdone by -\startpageht 219 | \ifpageafterfig 220 | \global\doingfigfalse 221 | \else 222 | \dimen0=\ht\figbox% 223 | \advance\dimen0 by 0.5\baselineskip% 224 | \ifdim\htdone<\dimen0% 225 | \dohangf 226 | \else 227 | \global\doingfigfalse 228 | \fi 229 | \fi 230 | \ifdoingfig\relax\else\global\figprocessingfalse\fi 231 | \else 232 | \global\outputpretest={\outputtrue}% 233 | \fi 234 | \fi 235 | } 236 | \def\trytab{% 237 | \iftryingtab% 238 | {\everypar={\relax}\setbox0=\lastbox% 239 | \parindent=\wd0 \parskip=0pt \par% 240 | \penalty-10005 \leavevmode}% 241 | \dimen0=\vsize% 242 | \advance\dimen0 by -\pageht% 243 | \advance\dimen0 by -2\baselineskip% 244 | \ifdim\dimen0>\ht\tabbox% 245 | \dimen0=0.3\baselineskip 246 | \vrule depth \dimen0 width 0pt 247 | \vadjust{\kern -\dimen0% 248 | \vtop to \dimen0{% 249 | \baselineskip=\dimen0% 250 | \vss \vbox to 1ex{% 251 | \ifoddpages% 252 | \hbox to \hsize{\hss\copy\tabbox}% 253 | \else% leftsetting 254 | \hbox to \hsize{\copy\tabbox\hss}% 255 | \fi% \ifodd\count0 256 | \vss}\null}}% 257 | \global\tryingtabfalse% 258 | \global\doingtabtrue 259 | \global\startpageht=\pageht 260 | \global\htdone=0pt 261 | \dohangt 262 | \ifnum\nosuccesstrytab>0% 263 | \typeout{floatflt Message: Flt. tab. \the\ftabcount\space set on page 264 | \the\count0, shifted \the\nosuccesstrytab\space par(s) forward.}% 265 | \else 266 | \typeout{Package floatflt Message: Floating table \the\ftabcount\space 267 | set on page \the\count0}% 268 | \fi 269 | \else 270 | \global\advance\nosuccesstrytab by 1 271 | \fi 272 | \else 273 | \ifdoingtab 274 | {\everypar={\relax}\setbox0=\lastbox 275 | \parindent=\wd0 \parskip=0pt \par 276 | \penalty-10005 \leavevmode}% 277 | \global\htdone=\pageht 278 | \global\advance\htdone by -\startpageht 279 | \ifpageaftertab 280 | \global\doingtabfalse 281 | \else 282 | \dimen0=\ht\tabbox% 283 | \advance\dimen0 by 0.5\baselineskip% 284 | \ifdim\htdone<\dimen0% 285 | \dohangt 286 | \else 287 | \global\doingtabfalse 288 | \fi 289 | \fi 290 | \ifdoingtab\relax\else\global\tabprocessingfalse\fi 291 | \else 292 | \global\outputpretest={\outputtrue}% 293 | \fi 294 | \fi 295 | } 296 | \def\figinsert{% 297 | \global\nosuccesstryfig=0% 298 | \global\outputpretest={\dofigtest}% 299 | \global\tryingfigtrue \global\doingfigfalse% 300 | \global\pageafterfigfalse}% 301 | \def\tabinsert{% 302 | \global\nosuccesstrytab=0% 303 | \global\outputpretest={\dotabtest}% 304 | \global\tryingtabtrue \global\doingtabfalse% 305 | \global\pageaftertabfalse}% 306 | \def\dohangf{% 307 | \dimen0=\ht\figbox% 308 | \advance\dimen0 by -\htdone% 309 | \advance\dimen0 by 1.49\baselineskip% 310 | \hangcount=\dimen0% 311 | \divide\hangcount by \baselineskip% 312 | \dimen0=\wd\figbox% 313 | \advance\dimen0 by \figgutter% 314 | \ifoddpages% 315 | \global\hangafter=-\hangcount% placing right 316 | \global\hangindent=-\dimen0% 317 | \else% \ifleftsetting 318 | \global\hangafter=-\hangcount% placing left 319 | \global\hangindent=\dimen0% 320 | \fi 321 | } 322 | \def\dohangt{% 323 | \dimen0=\ht\tabbox% 324 | \advance\dimen0 by -\htdone% 325 | \advance\dimen0 by 1.49\baselineskip% 326 | \hangcount=\dimen0% 327 | \divide\hangcount by \baselineskip% 328 | \dimen0=\wd\tabbox% 329 | \advance\dimen0 by \tabgutter% 330 | \ifoddpages% 331 | \global\hangafter=-\hangcount% placing right 332 | \global\hangindent=-\dimen0% 333 | \else% \ifleftsetting 334 | \global\hangafter=-\hangcount% placing left 335 | \global\hangindent=\dimen0% 336 | \fi 337 | } 338 | \newcommand{\fltitem}[2][0pt]{\setlength{\fltitemwidth}{\linewidth}% 339 | \addtolength{\fltitemwidth}{-\floatfltwidth}% 340 | \addtolength{\fltitemwidth}{-0.5em}% 341 | \item \parbox[t]{\fltitemwidth}{#2}\\[#1]} 342 | \newcommand{\fltditem}[3][0pt]{\setlength{\fltitemwidth}{\linewidth}% 343 | \addtolength{\fltitemwidth}{-\floatfltwidth}% 344 | \addtolength{\fltitemwidth}{-0.5em}% 345 | \item[#2] \parbox[t]{\fltitemwidth}{#3}\\[#1]} 346 | \endinput 347 | %% 348 | %% End of file `floatflt.sty'. 349 | -------------------------------------------------------------------------------- /gb_452.cap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cliffwoo/LSP_CN/aa76748ec4a9e96a0da20a3dd046e557b0a5bd50/gb_452.cap -------------------------------------------------------------------------------- /gb_452.cpx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cliffwoo/LSP_CN/aa76748ec4a9e96a0da20a3dd046e557b0a5bd50/gb_452.cpx -------------------------------------------------------------------------------- /gb_452_GBK_xelatex.cap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cliffwoo/LSP_CN/aa76748ec4a9e96a0da20a3dd046e557b0a5bd50/gb_452_GBK_xelatex.cap -------------------------------------------------------------------------------- /gb_452_GBK_xelatex.cpx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cliffwoo/LSP_CN/aa76748ec4a9e96a0da20a3dd046e557b0a5bd50/gb_452_GBK_xelatex.cpx -------------------------------------------------------------------------------- /gb_452_UTF8.cpx: -------------------------------------------------------------------------------- 1 | % -*-coding: utf-8 -*- 2 | % This is the file GB.cap of the CJK package 3 | % for using Asian logographs (Chinese/Japanese/Korean) with LaTeX2e 4 | % 5 | % created by aloft for Standard LaTeX document class. 6 | % 7 | % Version 4.5.2 (18-May-2003) 8 | % 9 | % $Id: gb_452.cap,v 1.2 2006/08/14 11:48:05 luckyfox Exp $ 10 | % 11 | 12 | \def\fileversion{4.5.2} 13 | \def\filedate{2003/05/18} 14 | \ProvidesFile{GB.cap}[\filedate\space\fileversion 15 | for Standard LaTeX document class] 16 | 17 | 18 | % Chinese captions 19 | % 20 | % character set: GB 2312-80 21 | % encoding: EUC 22 | 23 | \@ifundefined{CJKnumber} 24 | {\def\CJKnumber#1{\ifcase#1\or 25 | 一\or二\or三\or四\or五\or 26 | 六\or七\or八\or九\or十\or十一\fi}}{} 27 | 28 | \renewcommand\contentsname{目录} 29 | \renewcommand\listfigurename{插图} 30 | \renewcommand\listtablename{表格} 31 | 32 | \@ifundefined{chapter} 33 | {\renewcommand\refname{参考文献}} 34 | {\renewcommand\bibname{参考文献}} 35 | 36 | \renewcommand\indexname{索引} 37 | 38 | \renewcommand\figurename{图} 39 | 40 | \renewcommand\tablename{表} 41 | 42 | \newcommand\CJKprepartname{第} 43 | \newcommand\CJKpartname{部分} 44 | \newcommand\CJKthepart{\CJKnumber{\@arabic\c@part}} 45 | 46 | \@ifundefined{chapter}{}{ 47 | \newcommand\CJKprechaptername{第} 48 | \newcommand\CJKchaptername{章} 49 | \newcommand\CJKthechapter{\CJKnumber{\@arabic\c@chapter}}} 50 | 51 | \renewcommand\appendixname{附录~\@Alph\c@chapter} 52 | 53 | \@ifundefined{mainmatter} 54 | {\renewcommand\abstractname{摘要}}{} 55 | 56 | % \renewcommand\ccname{} % ? 57 | % \renewcommand\enclname{附件} 58 | % \newcommand\prepagename{} % ? 59 | % \newcommand\postpagename{} % ? 60 | % \renewcommand\headtoname{} % ? 61 | % \renewcommand\seename{} % ? 62 | 63 | \let\CJK@todaysave=\today 64 | \def\CJK@todaysmall{~\the\year~年~\the\month~月~\the\day~日} 65 | \def\CJK@todaybig{\CJKdigits{\the\year}年\CJKnumber{\the\month}月\CJKnumber{\the\day}日} 66 | \def\CJK@today{\CJK@todaysmall} 67 | \renewcommand\today{\CJK@today} 68 | \newcommand\CJKtoday[1][1]{% 69 | \ifcase#1\def\CJK@today{\CJK@todaysave} 70 | \or\def\CJK@today{\CJK@todaysmall} 71 | \or\def\CJK@today{\CJK@todaybig} 72 | \fi} 73 | 74 | % 75 | % modify the definitions of Standard LaTeX document class 76 | % 77 | \@ifundefined{chapter}{ 78 | \def\@part[#1]#2{% 79 | \ifnum \c@secnumdepth >\m@ne 80 | \refstepcounter{part}% 81 | % \addcontentsline{toc}{part}{\thepart\hspace{1em}#1}% 82 | \addcontentsline{toc}{part}{\CJKprepartname\expandafter\noexpand\CJKthepart\CJKpartname\hspace{1em}#1}% 83 | \else 84 | \addcontentsline{toc}{part}{#1}% 85 | \fi 86 | {\parindent \z@ \raggedright 87 | \interlinepenalty \@M 88 | \normalfont 89 | \ifnum \c@secnumdepth >\m@ne 90 | % \Large\bfseries \partname\nobreakspace\thepart 91 | \Large\bfseries \CJKprepartname\CJKthepart\CJKpartname 92 | \par\nobreak 93 | \fi 94 | \huge \bfseries #2% 95 | \markboth{}{}\par}% 96 | \nobreak 97 | \vskip 3ex 98 | \@afterheading} 99 | }{ 100 | \def\@part[#1]#2{% 101 | \ifnum \c@secnumdepth >-2\relax 102 | \refstepcounter{part}% 103 | % \addcontentsline{toc}{part}{\thepart\hspace{1em}#1}% 104 | \addcontentsline{toc}{part}{\CJKprepartname\expandafter\noexpand\CJKthepart\CJKpartname\hspace{1em}#1}% 105 | \else 106 | \addcontentsline{toc}{part}{#1}% 107 | \fi 108 | \markboth{}{}% 109 | {\centering 110 | \interlinepenalty \@M 111 | \normalfont 112 | \ifnum \c@secnumdepth >-2\relax 113 | % \huge\bfseries \partname\nobreakspace\thepart 114 | \huge\bfseries \CJKprepartname\CJKthepart\CJKpartname 115 | \par 116 | \vskip 20\p@ 117 | \fi 118 | \Huge \bfseries #2\par}% 119 | \@endpart} 120 | \if@twoside 121 | \def\chaptermark#1{% 122 | \markboth {\MakeUppercase{% 123 | \ifnum \c@secnumdepth >\m@ne 124 | \if@mainmatter 125 | % \@chapapp\ \thechapter. \ % 126 | \CJKprechaptername\CJKthechapter\CJKchaptername \ % 127 | \fi 128 | \fi 129 | #1}}{}}% 130 | \def\sectionmark#1{% 131 | \markright {\MakeUppercase{% 132 | \ifnum \c@secnumdepth >\z@ 133 | % \thesection. \ % 134 | \thesection \ % 135 | \fi 136 | #1}}} 137 | \else 138 | \def\chaptermark#1{% 139 | \markright {\MakeUppercase{% 140 | \ifnum \c@secnumdepth >\m@ne 141 | \if@mainmatter 142 | % \@chapapp\ \thechapter. \ % 143 | \CJKprechaptername\CJKthechapter\CJKchaptername \ % 144 | \fi 145 | \fi 146 | #1}}} 147 | \fi 148 | \def\@chapter[#1]#2{\ifnum \c@secnumdepth >\m@ne 149 | \if@mainmatter 150 | \refstepcounter{chapter}% 151 | % \typeout{\@chapapp\space\thechapter.}% 152 | \typeout{\CJKprechaptername\CJKthechapter\CJKchaptername}% 153 | \addcontentsline{toc}{chapter}% 154 | % {\protect\numberline{\thechapter}#1}% 155 | {\CJKprechaptername\ifx\CJKprechaptername\CJKthechapter\else~\fi%目录中,章的数字两边加入间距,如:第 1 章,同时保证目录中的附录前不会有空白 156 | \expandafter\noexpand\CJKthechapter\ifx\CJKprechaptername\CJKthechapter\else~\fi\CJKchaptername\hspace{0.8em}#1}% 157 | \else 158 | \addcontentsline{toc}{chapter}{#1}% 159 | \fi 160 | \else 161 | \addcontentsline{toc}{chapter}{#1}% 162 | \fi 163 | \chaptermark{#1}% 164 | % \addtocontents{lof}{\protect\addvspace{10\p@}}%把图表索引每章后面的空行去掉 by luckyfox 165 | % %\addtocontents{lot}{\protect\addvspace{10\p@}}% 166 | \if@twocolumn 167 | \@topnewpage[\@makechapterhead{#2}]% 168 | \else 169 | \@makechapterhead{#2}% 170 | \@afterheading 171 | \fi} 172 | \def\@makechapterhead#1{% 173 | \vspace*{50\p@}% 174 | {\parindent \z@ \raggedright \normalfont 175 | \ifnum \c@secnumdepth >\m@ne 176 | \if@mainmatter 177 | % \huge\bfseries \@chapapp\space \thechapter 178 | \huge\bfseries \CJKprechaptername\CJKthechapter\CJKchaptername 179 | \par\nobreak 180 | \vskip 20\p@ 181 | \fi 182 | \fi 183 | \interlinepenalty\@M 184 | \Huge \bfseries #1\par\nobreak 185 | \vskip 40\p@ 186 | }} 187 | \renewcommand*\l@chapter[2]{% 188 | \ifnum \c@tocdepth >\m@ne 189 | \addpenalty{-\@highpenalty}% 190 | \vskip 1.0em \@plus\p@ 191 | % \setlength\@tempdima{1.5em}% 192 | \setlength\@tempdima{0em}% 193 | \begingroup 194 | \parindent \z@ \rightskip \@pnumwidth 195 | \parfillskip -\@pnumwidth 196 | \leavevmode \bfseries 197 | \advance\leftskip\@tempdima 198 | \hskip -\leftskip 199 | #1\nobreak\hfil \nobreak\hb@xt@\@pnumwidth{\hss #2}\par 200 | \penalty\@highpenalty 201 | \endgroup 202 | \fi} 203 | \let\@appendix\appendix 204 | \renewcommand\appendix{\@appendix% 205 | \def\CJKprechaptername{\relax}% 206 | \def\CJKthechapter{\relax}% 207 | \def\CJKchaptername{\appendixname} 208 | \renewcommand{\theequation}{\thechapter-\arabic{equation}} 209 | \renewcommand{\thefigure}{\thechapter-\arabic{figure}} 210 | \renewcommand{\thetable}{\thechapter-\arabic{table}}} 211 | } %end of \@ifundefined{chapter} 212 | 213 | \def\numberline#1{\ifdim\@tempdima>0pt% 214 | \settowidth\@tempdimb{#1\space}% 215 | \ifdim\@tempdima<\@tempdimb% 216 | \@tempdima=\@tempdimb% 217 | \fi% 218 | \hb@xt@\@tempdima{#1\hfil}% 219 | \fi} 220 | 221 | \endinput 222 | -------------------------------------------------------------------------------- /lstdoc.sty: -------------------------------------------------------------------------------- 1 | %% 2 | %% This is file `lstdoc.sty', 3 | %% generated with the docstrip utility. 4 | %% 5 | %% The original source files were: 6 | %% 7 | %% listings.dtx (with options: `doc') 8 | %% 9 | %% Please read the software license in listings-1.3.dtx or listings-1.3.pdf. 10 | %% 11 | %% (w)(c) 1996--2004 Carsten Heinz and/or any other author listed 12 | %% elsewhere in this file. 13 | %% (c) 2006 Brooks Moses 14 | %% 15 | %% Send comments and ideas on the package, error reports and additional 16 | %% programming languages to . 17 | %% 18 | \def\filedate{2007/02/22} 19 | \def\fileversion{1.4} 20 | \ProvidesPackage{lstdoc} 21 | [\filedate\space\fileversion\space(Carsten Heinz)] 22 | \let\lstdoc@currversion\fileversion 23 | \RequirePackage[writefile]{listings}[2004/09/07] 24 | \newif\iffancyvrb \IfFileExists{fancyvrb.sty}{\fancyvrbtrue}{} 25 | \newif\ifcolor \IfFileExists{color.sty}{\colortrue}{} 26 | \lst@false 27 | \newif\ifhyper 28 | \@ifundefined{pdfoutput} 29 | {} 30 | {\ifnum\pdfoutput>\z@ \lst@true \fi} 31 | \@ifundefined{VTeXversion} 32 | {} 33 | {\ifnum\OpMode>\z@ \lst@true \fi} 34 | \lst@if \IfFileExists{hyperref.sty}{\hypertrue}{}\fi 35 | \newif\ifalgorithmicpkg \IfFileExists{algorithmic.sty}{\algorithmicpkgtrue}{} 36 | \newif\iflgrind \IfFileExists{lgrind.sty}{\lgrindtrue}{} 37 | \iffancyvrb \RequirePackage{fancyvrb}\fi 38 | \ifhyper \RequirePackage[colorlinks]{hyperref}\else 39 | \def\href#1{\texttt}\fi 40 | \ifcolor \RequirePackage{color}\fi 41 | \ifalgorithmicpkg \RequirePackage{algorithmic}\fi 42 | \iflgrind \RequirePackage{lgrind}\fi 43 | \RequirePackage{nameref} 44 | \RequirePackage{url} 45 | \renewcommand\ref{\protect\T@ref} 46 | \renewcommand\pageref{\protect\T@pageref} 47 | \def\lst@BeginRemark#1{% 48 | \begin{quote}\topsep0pt\let\small\footnotesize\small#1:} 49 | \def\lst@EndRemark{\end{quote}} 50 | \newenvironment{TODO} 51 | {\lst@BeginRemark{To do}}{\lst@EndRemark} 52 | \newenvironment{ALTERNATIVE} 53 | {\lst@BeginRemark{Alternative}}{\lst@EndRemark} 54 | \newenvironment{REMOVED} 55 | {\lst@BeginRemark{Removed}}{\lst@EndRemark} 56 | \newenvironment{OLDDEF} 57 | {\lst@BeginRemark{Old definition}}{\lst@EndRemark} 58 | \def\advise{\par\list\labeladvise 59 | {\advance\linewidth\@totalleftmargin 60 | \@totalleftmargin\z@ 61 | \@listi 62 | \let\small\footnotesize \small\sffamily 63 | \parsep \z@ \@plus\z@ \@minus\z@ 64 | \topsep6\p@ \@plus1\p@\@minus2\p@ 65 | \def\makelabel##1{\hss\llap{##1}}}} 66 | \let\endadvise\endlist 67 | \def\advisespace{\hbox{}\qquad} 68 | \def\labeladvise{$\to$} 69 | \newenvironment{syntax} 70 | {\list{}{\itemindent-\leftmargin 71 | \def\makelabel##1{\hss\lst@syntaxlabel##1,,,,\relax}}} 72 | {\endlist} 73 | \def\lst@syntaxlabel#1,#2,#3,#4\relax{% 74 | \llap{\scriptsize\itshape#3}% 75 | \def\lst@temp{#2}% 76 | \expandafter\lst@syntaxlabel@\meaning\lst@temp\relax 77 | \rlap{\hskip-\itemindent\hskip\itemsep\hskip\linewidth 78 | \llap{\ttfamily\lst@temp}\hskip\labelwidth 79 | \def\lst@temp{#1}% 80 | \ifx\lst@temp\lstdoc@currversion#1\fi}} 81 | \def\lst@syntaxlabel@#1>#2\relax 82 | {\edef\lst@temp{\zap@space#2 \@empty}} 83 | \newcommand*\syntaxnewline{\newline\hbox{}\kern\labelwidth} 84 | \newcommand*\syntaxor{\qquad or\qquad} 85 | \newcommand*\syntaxbreak 86 | {\hfill\kern0pt\discretionary{}{\kern\labelwidth}{}} 87 | \let\syntaxfill\hfill 88 | \def\alternative#1{\lst@true \alternative@#1,\relax,} 89 | \def\alternative@#1,{% 90 | \ifx\relax#1\@empty 91 | \expandafter\@gobble 92 | \else 93 | \ifx\@empty#1\@empty\else 94 | \lst@if \lst@false \else $\vert$\fi 95 | \textup{\texttt{#1}}% 96 | \fi 97 | \fi 98 | \alternative@} 99 | \long\def\m@cro@#1#2#3{\endgroup \topsep\MacroTopsep \trivlist 100 | \edef\saved@macroname{\string#3}% 101 | \def\makelabel##1{\llap{##1}}% 102 | \if@inlabel 103 | \let\@tempa\@empty \count@\macro@cnt 104 | \loop \ifnum\count@>\z@ 105 | \edef\@tempa{\@tempa\hbox{\strut}}\advance\count@\m@ne \repeat 106 | \edef\makelabel##1{\llap{\vtop to\baselineskip 107 | {\@tempa\hbox{##1}\vss}}}% 108 | \advance \macro@cnt \@ne 109 | \else \macro@cnt\@ne \fi 110 | \edef\@tempa{\noexpand\item[% 111 | #1% 112 | \noexpand\PrintMacroName 113 | \else 114 | \expandafter\noexpand\csname Print#2Name\endcsname % MODIFIED 115 | \fi 116 | {\string#3}]}% 117 | \@tempa 118 | \global\advance\c@CodelineNo\@ne 119 | #1% 120 | \SpecialMainIndex{#3}\nobreak 121 | \DoNotIndex{#3}% 122 | \else 123 | \csname SpecialMain#2Index\endcsname{#3}\nobreak % MODIFIED 124 | \fi 125 | \global\advance\c@CodelineNo\m@ne 126 | \ignorespaces} 127 | \def\macro{\begingroup 128 | \catcode`\\12 129 | \MakePrivateLetters \m@cro@ \iftrue {Macro}}% MODIFIED 130 | \def\environment{\begingroup 131 | \catcode`\\12 132 | \MakePrivateLetters \m@cro@ \iffalse {Env}}% MODIFIED 133 | \def\newdocenvironment#1#2#3#4{% 134 | \@namedef{#1}{#3\begingroup \catcode`\\12\relax 135 | \MakePrivateLetters \m@cro@ \iffalse {#2}}% 136 | \@namedef{end#1}{#4\endmacro}% 137 | \@ifundefined{Print#2Name}{\expandafter 138 | \let\csname Print#2Name\endcsname\PrintMacroName}{}% 139 | \@ifundefined{SpecialMain#2Index}{\expandafter 140 | \let\csname SpecialMain#2Index\endcsname\SpecialMainIndex}{}} 141 | \newdocenvironment{aspect}{Aspect}{}{} 142 | \def\PrintAspectName#1{} 143 | \def\SpecialMainAspectIndex#1{% 144 | \@bsphack 145 | \index{aspects:\levelchar\protect\aspectname{#1}}% 146 | \@esphack} 147 | \newdocenvironment{lstkey}{Key}{}{} 148 | \def\PrintKeyName#1{\strut\keyname{#1}\ } 149 | \def\SpecialMainKeyIndex#1{% 150 | \@bsphack 151 | \index{keys\levelchar\protect\keyname{#1}}% 152 | \@esphack} 153 | \newcounter{argcount} 154 | \def\labelargcount{\texttt{\#\arabic{argcount}}\hskip\labelsep$=$} 155 | \def\macroargs{\list\labelargcount 156 | {\usecounter{argcount}\leftmargin=2\leftmargin 157 | \parsep \z@ \@plus\z@ \@minus\z@ 158 | \topsep4\p@ \@plus\p@ \@minus2\p@ 159 | \itemsep\z@ \@plus\z@ \@minus\z@ 160 | \def\makelabel##1{\hss\llap{##1}}}} 161 | \def\endmacroargs{\endlist\@endparenv} 162 | \lst@RequireAspects{writefile} 163 | \newbox\lst@samplebox 164 | \lstnewenvironment{lstsample}[3][] 165 | {\global\let\lst@intname\@empty 166 | \gdef\lst@sample{#2}% 167 | \setbox\lst@samplebox=\hbox\bgroup 168 | \setkeys{lst}{language={},style={},tabsize=4,gobble=5,% 169 | basicstyle=\small\ttfamily,basewidth=0.51em,point={#1}} 170 | #3% 171 | \lst@BeginAlsoWriteFile{\jobname.tmp}} 172 | {\lst@EndWriteFile\egroup 173 | \ifdim \wd\lst@samplebox>.5\linewidth 174 | \begin{center}% 175 | \hbox to\linewidth{\box\lst@samplebox\hss}% 176 | \end{center}% 177 | \lst@sampleInput 178 | \else 179 | \begin{center}% 180 | \begin{minipage}{0.45\linewidth}\lst@sampleInput\end{minipage}% 181 | \qquad 182 | \begin{minipage}{0.45\linewidth}% 183 | \hbox to\linewidth{\box\lst@samplebox\hss}% 184 | \end{minipage}% 185 | \end{center}% 186 | \fi} 187 | \lst@InstallKeywords{p}{point}{pointstyle}\relax{keywordstyle}{}ld 188 | \lstnewenvironment{lstxsample}[1][] 189 | {\begingroup 190 | \setkeys{lst}{belowskip=-\medskipamount,language={},style={},% 191 | tabsize=4,gobble=5,basicstyle=\small\ttfamily,% 192 | basewidth=0.51em,point={#1}} 193 | \lst@BeginAlsoWriteFile{\jobname.tmp}} 194 | {\endgroup 195 | \endgroup} 196 | \def\lst@sampleInput{% 197 | \MakePercentComment\catcode`\^^M=10\relax 198 | \small\lst@sample 199 | {\setkeys{lst}{SelectCharTable=\lst@ReplaceInput{\^\^I}% 200 | {\lst@ProcessTabulator}}% 201 | \leavevmode \input{\jobname.tmp}}\MakePercentIgnore} 202 | \renewcommand\paragraph{\@startsection{paragraph}{4}{\z@}% 203 | {1.25ex \@plus1ex \@minus.2ex}% 204 | {-1em}% 205 | {\normalfont\normalsize\bfseries}} 206 | \def\lstref#1{\emph{\ref{#1} \nameref{#1}}} 207 | \def\@part[#1]#2{\ifhyper\phantomsection\fi 208 | \addcontentsline{toc}{part}{#1}% 209 | {\parindent\z@ \raggedright \interlinepenalty\@M 210 | \normalfont \huge \bfseries #2\markboth{}{}\par}% 211 | \nobreak\vskip 3ex\@afterheading} 212 | \renewcommand*\l@section[2]{% 213 | \addpenalty\@secpenalty 214 | \addvspace{.25em \@plus\p@}% 215 | \setlength\@tempdima{1.5em}% 216 | \begingroup 217 | \parindent \z@ \rightskip \@pnumwidth 218 | \parfillskip -\@pnumwidth 219 | \leavevmode 220 | \advance\leftskip\@tempdima 221 | \hskip -\leftskip 222 | #1\nobreak\hfil \nobreak\hb@xt@\@pnumwidth{\hss #2}\par 223 | \endgroup} 224 | \renewcommand*\l@subsection{\@dottedtocline{2}{0pt}{2.3em}} 225 | \renewcommand*\l@subsubsection{\@dottedtocline{3}{0pt}{3.2em}} 226 | \newcommand\ikeyname[1]{% 227 | \lstkeyindex{#1}{}% 228 | \lstaspectindex{#1}{}% 229 | \keyname{#1}} 230 | \newcommand\ekeyname[1]{% 231 | \@bsphack 232 | \lstkeyindex{#1}{}% 233 | \lstaspectindex{#1}{}% 234 | \@esphack} 235 | \newcommand\rkeyname[1]{% 236 | \@bsphack 237 | \lstkeyindex{#1}{}% 238 | \lstaspectindex{#1}{}% 239 | \@esphack{\rstyle\keyname{#1}}} 240 | \newcommand\icmdname[1]{% 241 | \@bsphack 242 | \lstaspectindex{#1}{}% 243 | \@esphack\texttt{\string#1}} 244 | \newcommand\rcmdname[1]{% 245 | \@bsphack 246 | \lstaspectindex{#1}{}% 247 | \@esphack\texttt{\rstyle\string#1}} 248 | \def\lstaspectindex#1#2{% 249 | \global\@namedef{lstkandc@\string#1}{}% 250 | \@ifundefined{lstisaspect@\string#1} 251 | {\index{unknown\levelchar 252 | \protect\texttt{\protect\string\string#1}#2}}% 253 | {\index{\@nameuse{lstisaspect@\string#1}\levelchar 254 | \protect\texttt{\protect\string\string#1}#2}}% 255 | } 256 | \def\lstkeyindex#1#2{% 257 | } 258 | \def\lstisaspect[#1]#2{% 259 | \global\@namedef{lstaspect@#1}{#2}% 260 | \lst@AddTo\lst@allkeysandcmds{,#2}% 261 | \@for\lst@temp:=#2\do 262 | {\ifx\@empty\lst@temp\else 263 | \global\@namedef{lstisaspect@\lst@temp}{#1}% 264 | \fi}} 265 | \gdef\lst@allkeysandcmds{} 266 | \def\lstprintaspectkeysandcmds#1{% 267 | \lst@true 268 | \expandafter\@for\expandafter\lst@temp 269 | \expandafter:\expandafter=\csname lstaspect@#1\endcsname\do 270 | {\lst@if\lst@false\else, \fi \texttt{\lst@temp}}} 271 | \def\lstcheckreference{% 272 | \@for\lst@temp:=\lst@allkeysandcmds\do 273 | {\ifx\lst@temp\@empty\else 274 | \@ifundefined{lstkandc@\lst@temp} 275 | {\typeout{\lst@temp\space not in reference guide?}}{}% 276 | \fi}} 277 | \newcommand*\lst{\texttt{lst}} 278 | \newcommand*\Cpp{C\texttt{++}} 279 | \let\keyname\texttt 280 | \let\keyvalue\texttt 281 | \let\hookname\texttt 282 | \newcommand*\aspectname[1]{{\normalfont\sffamily#1}} 283 | \DeclareRobustCommand\packagename[1]{% 284 | {\leavevmode\text@command{#1}% 285 | \switchfontfamily\sfdefault\rmdefault 286 | \check@icl #1\check@icr 287 | \expandafter}}% 288 | \renewcommand\packagename[1]{{\normalfont\sffamily#1}} 289 | \def\switchfontfamily#1#2{% 290 | \begingroup\xdef\@gtempa{#1}\endgroup 291 | \ifx\f@family\@gtempa\fontfamily#2% 292 | \else\fontfamily#1\fi 293 | \selectfont} 294 | \ifcolor 295 | \definecolor{darkgreen}{rgb}{0,0.5,0} 296 | \def\rstyle{\color{darkgreen}} 297 | \else 298 | \let\rstyle\empty 299 | \fi 300 | \gdef\lst@emails{} 301 | \newcommand*\lstthanks[2] 302 | {#1\lst@AddTo\lst@emails{,#1,<#2>}% 303 | \ifx\@empty#2\@empty\typeout{Missing email for #1}\fi} 304 | \newcommand*\lsthelper[3] 305 | {{\let~\ #1}% 306 | \lst@IfOneOf#1\relax\lst@emails 307 | {}{\typeout{^^JWarning: Unknown helper #1.^^J}}} 308 | \lstdefinelanguage[doc]{Pascal}{% 309 | morekeywords={alfa,and,array,begin,boolean,byte,case,char,const,div,% 310 | do,downto,else,end,false,file,for,function,get,goto,if,in,% 311 | integer,label,maxint,mod,new,not,of,or,pack,packed,page,program,% 312 | procedure,put,read,readln,real,record,repeat,reset,rewrite,set,% 313 | text,then,to,true,type,unpack,until,var,while,with,write,writeln},% 314 | sensitive=false,% 315 | morecomment=[s]{(*}{*)},% 316 | morecomment=[s]{\{}{\}},% 317 | morestring=[d]{'}} 318 | \lstdefinestyle{} 319 | {basicstyle={},% 320 | keywordstyle=\bfseries,identifierstyle={},% 321 | commentstyle=\itshape,stringstyle={},% 322 | numberstyle={},stepnumber=1,% 323 | pointstyle=\pointstyle} 324 | \def\pointstyle{% 325 | {\let\lst@um\@empty \xdef\@gtempa{\the\lst@token}}% 326 | \expandafter\lstkeyindex\expandafter{\@gtempa}{}% 327 | \expandafter\lstaspectindex\expandafter{\@gtempa}{}% 328 | \rstyle} 329 | \lstset{defaultdialect=[doc]Pascal,language=Pascal,style={}} 330 | \def\lstscanlanguages#1#2#3{% 331 | \begingroup 332 | \def\lst@DefDriver@##1##2##3##4[##5]##6{% 333 | \lst@false 334 | \lst@lAddTo\lst@scan{##6(##5),}% 335 | \begingroup 336 | \@ifnextchar[{\lst@XDefDriver{##1}##3}{\lst@DefDriver@@##3}}% 337 | \def\lst@XXDefDriver[##1]{}% 338 | \lst@InputCatcodes 339 | \def\lst@dontinput{#3}% 340 | \let\lst@scan\@empty 341 | \lst@for{#2}\do{% 342 | \lst@IfOneOf##1\relax\lst@dontinput 343 | {}% 344 | {\InputIfFileExists{##1}{}{}}}% 345 | \global\let\@gtempa\lst@scan 346 | \endgroup 347 | \let#1\@gtempa} 348 | \def\lstprintlanguages#1{% 349 | \def\do##1{\setbox\@tempboxa\hbox{##1\space\space}% 350 | \ifdim\wd\@tempboxa<.5\linewidth \wd\@tempboxa.5\linewidth 351 | \else \wd\@tempboxa\linewidth \fi 352 | \box\@tempboxa\allowbreak}% 353 | \begin{quote} 354 | \par\noindent 355 | \hyphenpenalty=\@M \rightskip=\z@\@plus\linewidth\relax 356 | \lst@BubbleSort#1% 357 | \expandafter\lst@NextLanguage#1\relax(\relax),% 358 | \end{quote}} 359 | \def\lst@NextLanguage#1(#2),{% 360 | \ifx\relax#1\else 361 | \def\lst@language{#1}\def\lst@dialects{(#2),}% 362 | \expandafter\lst@NextLanguage@ 363 | \fi} 364 | \def\lst@NextLanguage@#1(#2),{% 365 | \def\lst@temp{#1}% 366 | \ifx\lst@temp\lst@language 367 | \lst@lAddTo\lst@dialects{(#2),}% 368 | \expandafter\lst@NextLanguage@ 369 | \else 370 | \do{\lst@language 371 | \ifx\lst@dialects\lst@emptydialect\else 372 | \expandafter\lst@NormedDef\expandafter\lst@language 373 | \expandafter{\lst@language}% 374 | \space(% 375 | \lst@BubbleSort\lst@dialects 376 | \expandafter\lst@PrintDialects\lst@dialects(\relax),% 377 | )% 378 | \fi}% 379 | \def\lst@next{\lst@NextLanguage#1(#2),}% 380 | \expandafter\lst@next 381 | \fi} 382 | \def\lst@emptydialect{(),} 383 | \def\lst@PrintDialects(#1),{% 384 | \ifx\@empty#1\@empty empty\else 385 | \lst@PrintDialect{#1}% 386 | \fi 387 | \lst@PrintDialects@} 388 | \def\lst@PrintDialects@(#1),{% 389 | \ifx\relax#1\else 390 | , \lst@PrintDialect{#1}% 391 | \expandafter\lst@PrintDialects@ 392 | \fi} 393 | \def\lst@PrintDialect#1{% 394 | \lst@NormedDef\lst@temp{#1}% 395 | \expandafter\ifx\csname\@lst dd@\lst@language\endcsname\lst@temp 396 | \texttt{\underbar{#1}}% 397 | \else 398 | \texttt{#1}% 399 | \fi} 400 | \def\lst@IfLE#1#2\@empty#3#4\@empty{% 401 | \ifx #1\relax 402 | \let\lst@next\@firstoftwo 403 | \else \ifx #3\relax 404 | \let\lst@next\@secondoftwo 405 | \else 406 | \lowercase{\ifx#1#3}% 407 | \def\lst@next{\lst@IfLE#2\@empty#4\@empty}% 408 | \else 409 | \lowercase{\ifnum`#1<`#3}\relax 410 | \let\lst@next\@firstoftwo 411 | \else 412 | \let\lst@next\@secondoftwo 413 | \fi 414 | \fi 415 | \fi \fi 416 | \lst@next} 417 | \def\lst@BubbleSort#1{% 418 | \ifx\@empty#1\else 419 | \lst@false 420 | \expandafter\lst@BubbleSort@#1\relax,\relax,% 421 | \expandafter\lst@BubbleSort@\expandafter,\lst@sorted 422 | \relax,\relax,% 423 | \let#1\lst@sorted 424 | \lst@if 425 | \def\lst@next{\lst@BubbleSort#1}% 426 | \expandafter\expandafter\expandafter\lst@next 427 | \fi 428 | \fi} 429 | \def\lst@BubbleSort@#1,#2,{% 430 | \ifx\@empty#1\@empty 431 | \def\lst@sorted{#2,}% 432 | \def\lst@next{\lst@BubbleSort@@}% 433 | \else 434 | \let\lst@sorted\@empty 435 | \def\lst@next{\lst@BubbleSort@@#1,#2,}% 436 | \fi 437 | \lst@next} 438 | \def\lst@BubbleSort@@#1,#2,{% 439 | \ifx\relax#1\else 440 | \ifx\relax#2% 441 | \lst@lAddTo\lst@sorted{#1,}% 442 | \expandafter\expandafter\expandafter\lst@BubbleSort@@@ 443 | \else 444 | \lst@IfLE #1\relax\@empty #2\relax\@empty 445 | {\lst@lAddTo\lst@sorted{#1,#2,}}% 446 | {\lst@true \lst@lAddTo\lst@sorted{#2,#1,}}% 447 | \expandafter\expandafter\expandafter\lst@BubbleSort@@ 448 | \fi 449 | \fi} 450 | \def\lst@BubbleSort@@@#1\relax,{} 451 | \endinput 452 | %% 453 | %% End of file `lstdoc.sty'. 454 | -------------------------------------------------------------------------------- /main.bbl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cliffwoo/LSP_CN/aa76748ec4a9e96a0da20a3dd046e557b0a5bd50/main.bbl -------------------------------------------------------------------------------- /main.blg: -------------------------------------------------------------------------------- 1 | This is BibTeX, Version 0.99c (Web2C 7.5.7) 2 | The top-level auxiliary file: main.aux 3 | A level-1 auxiliary file: body/Ch1.aux 4 | A level-1 auxiliary file: body/Ch4.aux 5 | A level-1 auxiliary file: body/Ch6.aux 6 | I found no \citation commands---while reading file main.aux 7 | I found no \bibdata command---while reading file main.aux 8 | I found no \bibstyle command---while reading file main.aux 9 | You've used 0 entries, 10 | 0 wiz_defined-function locations, 11 | 86 strings with 518 characters, 12 | and the built_in function-call counts, 0 in all, are: 13 | = -- 0 14 | > -- 0 15 | < -- 0 16 | + -- 0 17 | - -- 0 18 | * -- 0 19 | := -- 0 20 | add.period$ -- 0 21 | call.type$ -- 0 22 | change.case$ -- 0 23 | chr.to.int$ -- 0 24 | cite$ -- 0 25 | duplicate$ -- 0 26 | empty$ -- 0 27 | format.name$ -- 0 28 | if$ -- 0 29 | int.to.chr$ -- 0 30 | int.to.str$ -- 0 31 | missing$ -- 0 32 | newline$ -- 0 33 | num.names$ -- 0 34 | pop$ -- 0 35 | preamble$ -- 0 36 | purify$ -- 0 37 | quote$ -- 0 38 | skip$ -- 0 39 | stack$ -- 0 40 | substring$ -- 0 41 | swap$ -- 0 42 | text.length$ -- 0 43 | text.prefix$ -- 0 44 | top$ -- 0 45 | type$ -- 0 46 | warning$ -- 0 47 | while$ -- 0 48 | width$ -- 0 49 | write$ -- 0 50 | (There were 3 error messages) 51 | -------------------------------------------------------------------------------- /main.tex: -------------------------------------------------------------------------------- 1 | % -*-coding: utf-8 -*- 2 | 3 | \def\usewhat{xelatex} % 你喜欢哪种编译方式,pdflatex dvipdfmx dvipspdf xelatex yap 4 | 5 | %定义xelatex的中间临时变量,若\usewhat为xelatex时,后面执行xelatx的相关选项 6 | \def\atempxetex{xelatex} %这一项无需改动 7 | %input "reference\reference.bib" %for winedt users 8 | \def\version{1.9.2.20090324} % 该变量仅用于模板文件的版本号控制,新的论文规范从1.9开始; 9 | 10 | \def \xuewei {Doctor} % 定义学位 博士 11 | %\def \xuewei {Master} % 硕士 12 | 13 | \def\oneortwoside{twoside} %定义单双面打印,只对硕士学位论文有效; 14 | %\def\oneortwoside{oneside} % 硕士单面打印 15 | 16 | \def\xueke{Engineering} % 定义学科 工学 17 | %\def\xueke{Science} % 理学 18 | %\def\xueke{Management} % 管理学 19 | %\def\xueke{Arts} % 艺术学 20 | 21 | \input{setup/type.tex} % 硕博类型 22 | 23 | %下面的book选项中可以使用 draft 选项,使插入的图形只显示外框,以加快预览速度。 24 | \documentclass[12pt,a4paper,openany,\oneortwoside]{book} 25 | 26 | \input{setup/package.tex} % 引用的宏包 27 | 28 | % 论文包含的内容 29 | \includeonly{ 30 | body/Preface, 31 | body/Copyright, 32 | body/Ch1, 33 | body/Ch2, 34 | body/Ch3, 35 | body/Ch4, 36 | body/Ch5, 37 | body/Ch6, 38 | body/Ch7, 39 | body/Ch8, 40 | body/Ch9, 41 | body/Ch10, 42 | appendix/appA, 43 | appendix/bibliography, 44 | } 45 | \graphicspath{{figures/}} %定义所有的eps文件在 figures 子目录下 46 | 47 | \begin{document} 48 | \ifx\atempxetex\usewhat\else 49 | \begin{CJK*}{UTF8}{song} 50 | \fi 51 | 52 | \input{setup/Definition} % 文本格式定义 53 | \input{setup/format} 54 | 55 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 56 | % 正文部分 57 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 58 | \frontmatter 59 | \sloppy % 解决中英文混排的断行问题,会加入间距,但不会影响断行 60 | \input{preface/cover} % 封面 61 | \include{body/Preface} 62 | \include{body/Copyright} 63 | 64 | %% 中英目录 65 | \renewcommand{\baselinestretch}{1} 66 | \fontsize{12pt}{12pt}\selectfont 67 | \clearpage{\pagestyle{empty}\cleardoublepage} 68 | \pdfbookmark[0]{目~~~~录}{mulu} 69 | \tableofcontents % 中文目录 70 | \ifxueweidoctor % 英文目录右开 71 | \clearpage{\pagestyle{empty}\cleardoublepage} 72 | \else% 73 | \ifoneortwoside\clearpage{\pagestyle{empty}\cleardoublepage}\fi 74 | \fi 75 | \renewcommand{\baselinestretch}{1.3} 76 | \fontsize{12pt}{12pt}\selectfont 77 | % \ifxueweidoctor %硕士学位论文没有英文目录 78 | % \tableofengcontents % 英文目录 79 | % \fi 80 | 81 | % \input{setup/figtab.tex} %图表索引, 如果不需要图表索引,注释掉这一句即可; 82 | % % \notation %主要符号表 83 | % \addtocontents{toc}{\protect\vskip1\baselineskip} % 中文目录增加空行 84 | % \addtocontents{toe}{\protect\vskip1\baselineskip} % 英文目录增加空行 85 | 86 | % \ifxueweidoctor 87 | % \clearpage{\pagestyle{empty}\cleardoublepage} % 清除目录后面空页的页眉和页脚 88 | % \else% 89 | % \ifoneortwoside\clearpage{\pagestyle{empty}\cleardoublepage}\fi % 清除目录后面空页的页眉和页脚 90 | % \fi % 第一章是否右开 91 | 92 | \mainmatter 93 | \defaultfont % 对应于小四的标准字号为12pt, 可以在正文中用此命令修改所需要字体的的大小 94 | 95 | \include{body/Ch1} 96 | \include{body/Ch2} 97 | \include{body/Ch3} 98 | \include{body/Ch4} 99 | \include{body/Ch5} 100 | \include{body/Ch6} 101 | \include{body/Ch7} 102 | \include{body/Ch8} 103 | \include{body/Ch9} 104 | \include{body/Ch10} 105 | \include{appendix/appA} % 附录A 106 | \include{appendix/bibliography} % 参考文献 107 | 108 | \clearpage 109 | \ifx\atempxetex\usewhat\else 110 | \end{CJK*} 111 | \fi 112 | 113 | \end{document} 114 | 115 | %%% Local Variables: 116 | %%% mode: latex 117 | %%% TeX-master: t 118 | %%% End: 119 | -------------------------------------------------------------------------------- /makefile: -------------------------------------------------------------------------------- 1 | DVIPDFMX:=$(shell grep '\\def\\usewhat{dvipdfmx}' main.tex) 2 | PDFLATEX:=$(shell grep '\\def\\usewhat{pdflatex}' main.tex) 3 | DVIPSPDF:=$(shell grep '\\def\\usewhat{dvipspdf}' main.tex) 4 | XELATEX:=$(shell grep '\\def\\usewhat{xelatex}' main.tex) 5 | YAP:=$(shell grep '\\def\\usewhat{yap}' main.tex) 6 | PDFREADER:=evince 7 | 8 | empty= 9 | 10 | all: 11 | ifneq ($(empty),$(XELATEX)) 12 | xelatex main.tex 13 | xelatex main.tex 14 | # @echo Done. Starting the browser...... 15 | # @$(PDFREADER) main.pdf >/dev/null 2>&1 & 16 | endif 17 | ifneq ($(empty),$(PDFLATEX)) 18 | @echo Making pdflatex...... 19 | rm main_pdflatex.pdf& 20 | pdflatex main.tex 21 | env BIBINPUTS=./ BSTINPUTS=./ bibtex main 22 | pdflatex main.tex 23 | #gbk2uni main.out 24 | #pdflatex main.tex 25 | #mv main.pdf main_pdflatex.pdf 26 | @echo Done. Starting the browser...... 27 | @$(PDFREADER) main_pdflatex.pdf >/dev/null 2>&1 & 28 | endif 29 | ifneq ($(empty),$(DVIPDFMX)) 30 | @echo Making dvipdfmx...... 31 | rm main_dvipdfm.pdf main.dvi& 32 | latex main.tex 33 | # env BIBINPUTS=./ BSTINPUTS=./ bibtex main 34 | latex main.tex 35 | gbk2uni main.out 36 | latex main.tex 37 | dvipdfmx -p a4 main.dvi 38 | mv main.pdf main_dvipdfm.pdf 39 | @echo Done. Starting the browser...... 40 | @$(PDFREADER) main_dvipdfm.pdf >/dev/null 2>&1 & 41 | endif 42 | ifneq ($(empty),$(DVIPSPDF)) 43 | @echo Making dvipspdf...... 44 | rm main_dvipspdf.pdf main.dvi main.ps& 45 | latex main.tex 46 | # env BIBINPUTS=./ BSTINPUTS=./ bibtex main 47 | latex main.tex 48 | gbk2uni main.out 49 | latex main.tex 50 | dvips -G0 -ta4 main.dvi 51 | ps2pdf main.ps main_dvipspdf.pdf 52 | @echo Done. Starting the browser...... 53 | @$(PDFREADER) main_dvipspdf.pdf >/dev/null 2>&1 & 54 | endif 55 | ifneq ($(empty),$(YAP)) 56 | @echo Making dvi...... 57 | rm main.dvi& 58 | latex main.tex 59 | env BIBINPUTS=./ BSTINPUTS=./ bibtex main 60 | latex main.tex 61 | gbk2uni main.out 62 | latex main.tex 63 | xdvi main.dvi& 64 | endif 65 | 66 | clean: 67 | @echo Cleaning up...... 68 | -rm *.log *.out *.thm *.toc *.toe *.pdf 69 | -rm body/*.aux 70 | @echo All done. 71 | -------------------------------------------------------------------------------- /preface/cover.tex: -------------------------------------------------------------------------------- 1 | % -*-coding: utf-8 -*- 2 | 3 | % \newcommand{\chinesethesistitle}{哈尔滨工业大学硕博士学位论文~\LaTeX~模板~(\version~版)} %授权书用,无需断行 4 | % \newcommand{\englishthesistitle}{\LaTeX~Dissertation Template of \\Harbin Institute of Technology~(Version \version)} 5 | % \newcommand{\chinesethesistime}{2009~年~1~月} %封面底部的日期中文形式 6 | % \newcommand{\englishthesistime}{January, 2009} %封面底部的日期英文形式 7 | 8 | % \ctitle{哈尔滨工业大学硕博士学位论文\\ \LaTeX~模板~(\version~版)} %封面用论文标题,自己可手动断行 9 | % \cdegree{\cxueke\cxuewei} 10 | % \csubject{计算机系统结构} %(~按二级学科填写~) 11 | % \caffil{计算机科学与技术学院} %(在校生填所在系名称,同等学力人员填工作单位) 12 | % \cauthor{某~~某~~某} 13 | % \csupervisor{某~~某~~某~~~~教~~授} %导师名字 14 | % %\cassosupervisor{某~~~~~~某~~~~教~~授} %(~如无副导师可以不列此项~) 15 | % %\ccosupervisor{某~~某~~某~~~~教~~授~} %(~如无联合培养导师则不列此项~) 16 | % \cdate{\chinesethesistime} 17 | 18 | % \etitle{\englishthesistitle} 19 | % \edegree{\exuewei \ of \exueke} 20 | % \esubject{Microelectronics \hfill and \hfill Solid-State\newline Electronics} %英文二级学科名 21 | % \eaffil{Dept.\hfill of\hfill Microelectronics\hfill Science\newline and Technology}%英文单位 %换行用\newline,不要用\\ 22 | % \eauthor{Alice} %作者姓名 (英文) 23 | % \esupervisor{Professor Bob} % 导师姓名 (英文) 24 | % %\ecosupervisor{Professor X} 25 | % %\eassosupervisor{Professor Y} 26 | % \edate{\englishthesistime} 27 | 28 | % \natclassifiedindex{TP309} %国内图书分类号 29 | % \internatclassifiedindex{681.324} %国际图书分类号 30 | % \statesecrets{公开} %秘密 31 | 32 | % \ iffalse 33 | % \BiAppendixChapter{版权声明}{} %使用winedt编辑时文档结构图(toc)中为了显示摘要,故增加此句; 34 | % \fi 35 | % \cabstract{} 36 | % \begin{titlepage} 37 | % \begin{center} 38 | % \begin{figure} 39 | % \centering 40 | % \includegraphics{./figures/lspcover1.jpg} 41 | % \end{figure} 42 | % \end{center} 43 | % \end{titlepage} 44 | \makecover 45 | \clearpage 46 | -------------------------------------------------------------------------------- /reference/reference.bib: -------------------------------------------------------------------------------- 1 | % -*-coding: utf-8 -*- 2 | 3 | @BOOK{BEZOS02, 4 | AUTHOR = "J. Bezos", 5 | FULLAUTHOR = "Javier Bezos", 6 | TITLE = "The titlesec and titletoc Packages", 7 | PUBLISHER = "University of SomeName", 8 | MONTH = "March", 9 | YEAR = "2002", 10 | Pages = "10--20", 11 | Edition = "2nd", 12 | ADDRESS = "Cityname", 13 | } 14 | 15 | @BOOK{OOSTRUM01, 16 | AUTHOR = "{P. Oostrum, ifuleyou@bbs.ctex.org~译}", 17 | FULLAUTHOR = "Piet van Oostrum", 18 | TITLE = "{\LaTeX}下的页面布局", 19 | PUBLISHER = "某某大学出版社", 20 | MONTH = "August", 21 | YEAR = "2001", 22 | Pages = "10--20", 23 | ADDRESS = "哈尔滨", 24 | } 25 | 26 | @ARTICLE{SHELL02, 27 | AUTHOR = "Michael Shell", 28 | TITLE = "How to Use the {IEEEtran} {\LaTeX} Class", 29 | JOURNAL = "Journal of {\LaTeX} Class Files", 30 | VOLUME = "1", 31 | NUMBER = "11", 32 | MONTH = "November", 33 | YEAR = "2002", 34 | Pages = "10--20", 35 | } 36 | 37 | @BOOK{TEXGURU99, 38 | AUTHOR = "{\TeX}Guru", 39 | TITLE = "{\LaTeX 2$\varepsilon$}用户手册", 40 | PUBLISHER = "某某大学出版社", 41 | YEAR = "1999", 42 | Pages = "10--20", 43 | ADDRESS = "哈尔滨", 44 | } 45 | 46 | @BOOK{WANG00, 47 | AUTHOR = "{K. Reckdahl~原著, 王磊~译}", 48 | FULLAUTHOR = "Keith Reckdahl, 王磊~译", 49 | TITLE = "Using Import graphics in {\LaTeX 2$\varepsilon$}, {\LaTeX 2$\varepsilon$}插图指南", 50 | PUBLISHER = "某某大学出版社", 51 | YEAR = "2000", 52 | Pages = "10--20", 53 | ADDRESS = "哈尔滨", 54 | } 55 | 56 | 57 | @BOOK{Zhang2002, 58 | AUTHOR = "张三 and 李四 and 王五 and 马六 and 麻七", 59 | FULLAUTHOR = "张三 and 李四 and 王五 and 马六 and 麻七", 60 | TITLE = "七仙女下凡除妖记", 61 | PUBLISHER = "某某大学出版社", 62 | MONTH = "7月", 63 | YEAR = "2002", 64 | Pages = "1--200", 65 | Edition = "第二版", 66 | ADDRESS = "哈尔滨", 67 | } 68 | 69 | @phdthesis{zhangsanfeng, 70 | Author = {Zhang,S. F.}, 71 | Title = {Tai ji jian and tai ji quan}, 72 | School = {wu dang university}, 73 | Year = {1783}, 74 | pages= {15--16}, 75 | ADDRESS = "Harbin", 76 | } 77 | 78 | 79 | @BOOK{Lin1992, 80 | AUTHOR = "林来兴", 81 | FULLAUTHOR = "", 82 | TITLE = "空间控制技术", 83 | PUBLISHER = "宇航出版社", 84 | YEAR = "1992", 85 | Pages = "25--42", 86 | ADDRESS = "哈尔滨", 87 | } 88 | 89 | @ARTICLE{McDonnell1994, 90 | AUTHOR = {J. R. McDonnell and D. Wagen}, 91 | TITLE = {Evolving Recurrent Perceptions for Time-{S}eries Modeling}, 92 | JOURNAL = {IEEE Trans. on Neural Networks}, 93 | YEAR = {1994}, 94 | volume = {5}, 95 | number = {1}, 96 | pages = {24--38}, 97 | } 98 | 99 | @ARTICLE{Yao1993, 100 | AUTHOR = {X.Yao}, 101 | TITLE = {Evolutionary Artifitial Neural Networks}, 102 | JOURNAL = {J. Of Neural Systems}, 103 | YEAR = {1993}, 104 | volume = {}, 105 | number = {4}, 106 | pages = {203--222}, 107 | } 108 | 109 | @phdthesis{Chen1992, 110 | Author = {谌颖}, 111 | Title = {空间最优交会控制理论与方法研究}, 112 | School = {哈尔滨工业大学}, 113 | Year = {1992}, 114 | type = {博士学位论文}, 115 | pages= {8--13}, 116 | ADDRESS = "哈尔滨", 117 | } 118 | 119 | @CONFERENCE{Niwa1990, 120 | author = {S.Niwa and M. Suzuki and K. Kimura}, 121 | title = {Electrical Shock Absorber for Docking System Space}, 122 | booktitle = {IEEE International Workshop on Intelligent Motion Control}, 123 | year = {1990}, 124 | pages = {825--830}, 125 | address = {Istenbul}, 126 | publisher = {Bogazici University}, 127 | } 128 | 129 | @CONFERENCE{wu1997, 130 | author = {吴葳 and 洪炳熔}, 131 | title = {自由浮游空间机器人捕捉目标的运动规划研究}, 132 | booktitle = {{ 中国第五届机器人学术会议论文集 }}, 133 | year = {1997}, 134 | pages = {75--80}, 135 | address = {哈尔滨}, 136 | publisher = {某某出版社}, 137 | } 138 | 139 | @ARTICLE{wwwlixing, 140 | AUTHOR = "李兴 and 吴诗其", 141 | TITLE = "宽带IP卫星通信技术", 142 | JOURNAL = "\url{http://www.opnet.com/products/home.html}", 143 | VOLUME = "", 144 | NOTE = "", 145 | NUMBER = "", 146 | MONTH = "", 147 | YEAR = "", 148 | PAGES = "", 149 | } 150 | -------------------------------------------------------------------------------- /setup/Definition.tex: -------------------------------------------------------------------------------- 1 | % -*-coding: utf-8 -*- 2 | 3 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 4 | % 重定义字体命令 5 | % 注意win2000,没有 simsun, 最好到网上找一个 6 | % 一些字体是office2000 带的 7 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 8 | \ifx\atempxetex\usewhat 9 | % xelatex调用系统字体; 10 | % 【请在命令行下用 "fc-list" 列出系统的字体,选择其对应的名字】 11 | % 【只列出中文字体的命令 "fc-list :lang=zh-cn" 】 12 | \defaultfontfeatures{Mapping=tex-text} 13 | \setmainfont{Times New Roman} % 正文中的英文 采用 Times New Roman 字体; 14 | \setsansfont{Times New Roman} % 正文中的英文 采用 Times New Roman 字体; 15 | \setmonofont{Courier New} 16 | \setCJKmainfont{SimSun} 17 | \setCJKsansfont{SimHei} 18 | %\setCJKmonofont{LiSu} 19 | \setCJKmonofont{SimSun} 20 | \setCJKfamilyfont{song}{SimSun} 21 | \setCJKfamilyfont{hei}{SimHei} 22 | \setCJKfamilyfont{fs}{FangSong} % XP对应 FangSong_GB2312,Vista对应FangSong,注意根据系统切换 23 | \setCJKfamilyfont{kai}{KaiTi} % XP对应 KaiTi_GB2312,Vista对应KaiTi,注意根据系统切换 24 | \setCJKfamilyfont{li}{LiSu} 25 | \fi 26 | \newcommand{\song}{\CJKfamily{song}} % 宋体 (Windows自带simsun.ttf) 27 | \newcommand{\fs}{\CJKfamily{fs}} % 仿宋体 (Windows自带simfs.ttf) 28 | \newcommand{\kai}{\CJKfamily{kai}} % 楷体 (Windows自带simkai.ttf) 29 | \newcommand{\hei}{\CJKfamily{hei}} % 黑体 (Windows自带simhei.ttf) 30 | \newcommand{\li}{\CJKfamily{li}} % 隶书 (Windows自带simli.ttf) 31 | 32 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 33 | % 重定义字号命令 34 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 35 | \newcommand{\yihao}{\fontsize{26pt}{26pt}\selectfont} % 一号, 1.倍行距 36 | \newcommand{\xiaoyi}{\fontsize{24pt}{24pt}\selectfont} % 小一, 1.倍行距 37 | \newcommand{\erhao}{\fontsize{22pt}{22pt}\selectfont} % 二号, 1.倍行距 38 | \newcommand{\xiaoer}{\fontsize{18pt}{18pt}\selectfont} % 小二, 单倍行距 39 | \newcommand{\sanhao}{\fontsize{16pt}{16pt}\selectfont} % 三号, 1.倍行距 40 | \newcommand{\xiaosan}{\fontsize{15pt}{15pt}\selectfont} % 小三, 1.倍行距 41 | \newcommand{\sihao}{\fontsize{14pt}{14pt}\selectfont} % 四号, 1.0倍行距 42 | \newcommand{\banxiaosi}{\fontsize{13pt}{13pt}\selectfont} % 半小四, 1.0倍行距 43 | \newcommand{\xiaosi}{\fontsize{12pt}{12pt}\selectfont} % 小四, 1.倍行距 44 | \newcommand{\dawuhao}{\fontsize{11.5pt}{11.5pt}\selectfont} % 大五号, 单倍行距 45 | \newcommand{\wuhao}{\fontsize{10.5pt}{10.5pt}\selectfont} % 五号, 单倍行距 46 | \newcommand{\xiaowu}{\fontsize{9.5pt}{9.5pt}\selectfont} % 五号, 单倍行距 47 | \newcommand{\banbanxiaosi}{\fontsize{12pt}{12pt}\selectfont}% 半半小四, 1.0倍行距 48 | 49 | %避免宏包 hyperref 和 arydshln 不兼容带来的目录链接失效的问题。 50 | \def\temp{\relax} 51 | \let\temp\addcontentsline 52 | \gdef\addcontentsline{\phantomsection\temp} 53 | \newcommand*{\subfigencaptionlist}{} % 子图形加入目录时用 54 | 55 | \makeatletter 56 | \gdef\hitempty{} 57 | 58 | \newcommand{\mr}[1]{\mathrm{#1}} %定义新命令,用\mr来代替\mathrm 59 | \def \ReferenceEName {References} %%定义参考文献的标题 60 | \def \ReferenceCName {参考文献} 61 | 62 | %定义图表章节双标题命令 63 | \newcommand{\figenname}{Fig.} 64 | \newcommand{\listfigenname}{List of Figures} 65 | \newfloatlist[chapter]{figen}{fen}{\listfigenname}{\figenname} 66 | \newfixedcaption{\figencaption}{figen} 67 | \renewcommand{\thefigen}{\thechapter-\arabic{figure}} 68 | \renewcommand{\@cftmakefentitle}{\chapter*{\listfigenname\@mkboth{\bfseries\listfigenname}{\bfseries\listfigenname}}} 69 | 70 | 71 | \newcommand{\FigureBiCaption}[2] 72 | {\renewcommand{\figurename}{图} 73 | \caption{\protect\setlength{\baselineskip}{1.5em}#1} %\protect\setlength{\baselinestretch}{1.3}\selectfont 74 | \vspace{-1.3ex}%-0.5ex 75 | \figencaption{\protect\setlength{\baselineskip}{1.5em}#2}% 76 | \vspace{-3.4mm} 77 | %% 78 | %%其子图形加入目录 79 | \def\hittemp{} 80 | \@for \hittemp:=\subfigencaptionlist \do {% 81 | \ifx \hitempty\hittemp\relax \else 82 | \addcontentsline{fen}{subfigen}{\protect\numberline\hittemp} 83 | \fi} 84 | \gdef\subfigencaptionlist{} 85 | } 86 | 87 | \setcounter{fendepth}{2} %英文图形目录的深度 1(只有一级目录) 2(有两级目录) 88 | \setcounter{lofdepth}{2} %中文图形目录的深度 1(只有一级目录) 2(有两级目录) 89 | \renewcommand*{\l@subfigure}{\@dottedxxxline{\ext@subfigure}{2}{3.8em}{1.5em}} %中文图形目录 subfigure 90 | \gdef\l@subfigen{\@dottedtocline{2}{3.8em}{1.5em}}%英文图形目录 latex 91 | \newif\ifsubfigtoc 92 | \ifnum \tw@ > \@nameuse{c@fendepth} \subfigtocfalse \else \subfigtoctrue \fi 93 | \newbox\tempbox 94 | \renewcommand*{\subcapsize}{\wuhao} %设置子图英文标题的字号为五号; 95 | \def\SubfigEnCaption{% 96 | \@ifnextchar [% 97 | {\SubfigEnCap}% 98 | {\SubfigEnCap[0pt]} 99 | } \long\def\SubfigEnCap[#1]#2 %产生caption 有水平间距调整 100 | { \ifsubfigtoc %加入目录这个动作,一定要在 父图 之后,所在先暂存在 subfigencaptionlist 101 | \protected@xdef\subfigencaptionlist{\subfigencaptionlist,% 102 | {{\thesubfigure}\protect\ignorespaces{#2}}} 103 | \fi \vspace{1pt} 104 | \sbox{\tempbox}{\thesubfigure\hskip\subfiglabelskip #2}% 105 | \ifthenelse{\lengthtest{\wd\tempbox > \linewidth}}% 106 | {\\[-20pt]\hspace*{#1}\parbox[t]{\linewidth}{\flushleft\noindent\wuhao\selectfont\thesubfigure\hskip\subfiglabelskip \centering#2\hangafter=1\hangindent=15pt}}% 107 | {\\\hspace*{#1}\centerline{\wuhao\selectfont\thesubfigure\hskip\subfiglabelskip #2}} 108 | } 109 | 110 | %\newcommand{\SubfigureCaption}[2] % Two Parameters, the first one is the width of the subfigure, 111 | %{ 112 | %\addtocounter{subfigure}{-1} % the second one is the caption of the subfigure 113 | %\vspace{-2ex} 114 | %\subfigure[#2]{\rule{#1}{0pt}} 115 | %} 116 | 117 | \newcommand{\tblenname}{Table} %define tbl instead of table 118 | \newcommand{\listtblenname}{List of Tables} 119 | \newfloatlist[chapter]{tblen}{ten}{\listtblenname}{\tblenname} 120 | \newfixedcaption{\tblencaption}{tblen} 121 | \renewcommand{\thetblen}{\thechapter-\arabic{table}}% 将tblen换成table,因为table和tablen编号一致,而tablen在\longbitoccaption定义中无效。 122 | \renewcommand{\@cftmaketentitle}{\chapter*{\listtblenname\@mkboth{\bfseries\listtblenname}{\bfseries\listtblenname}}} 123 | 124 | 125 | \newcommand{\TableBiCaption}[2] 126 | { 127 | \renewcommand{\tablename}{表} 128 | \caption{\protect\setlength{\baselineskip}{1.5em}#1} 129 | \vspace{-2ex} 130 | \tblencaption{\protect\setlength{\baselineskip}{1.5em}#2} 131 | \vspace{1ex} 132 | } 133 | 134 | %%%% 长表格的caption在中英文表格目录中正常显示 135 | \setlength{\LTcapwidth}{\textwidth} %长表格宽度 136 | \def\@cont@LT@LTBiToeCaption#1[#2]#3{% 137 | \LT@makecaption#1\fnum@table{#3}% 138 | \def\@tempa{#2}% 139 | \ifx\@tempa\@empty\else 140 | {\let\\\space 141 | %\phantomsection 142 | \addcontentsline{ten}{tblen}{\protect\numberline{\thetable}{#2}}}%%\addcontentsline{lot}{table}{\protect\numberline{}{#2}}}% 143 | \fi} 144 | \def\LT@c@ption#1[#2]#3{% 145 | \LT@makecaption#1\fnum@table{#3}% 146 | \def\@tempa{#2}% 147 | \ifx\@tempa\@empty\else 148 | {\let\\\space 149 | %\phantomsection 150 | \addcontentsline{lot}{table}{\protect\numberline{\thetable}{#2}}}% 151 | \fi} 152 | \let\@cont@oldLT@c@ption\LT@c@ption 153 | \newcommand*{\LTBiTocCaption}[5]{ 154 | \@if@contemptyarg{#1}{\caption{\centering #2}}{\caption[#1]{\centering #2}}% 155 | \global\let\@cont@oldtablename\tablename 156 | \gdef\tablename{Table} %#3 157 | \global\let\LT@c@ption\@cont@LT@LTBiToeCaption 158 | \\ 159 | \@if@contemptyarg{#4}{\caption{\centering #5}}{\caption[#4]{\centering #5}}% 160 | \global\let\tablename\@cont@oldtablename 161 | \global\let\LT@c@ption\@cont@oldLT@c@ption} 162 | 163 | \renewcommand{\cfttblendotsep}{1} %自定义图表目录中的点间距大小 164 | \renewcommand{\cftfigendotsep}{1} 165 | 166 | %\renewcommand{\tablename}{表} %jdg提供的一种方法,英文长表会添加到中文目录中去,上面定义 167 | %\newcommand{\LTBiCaption}[2] %\bicaptiontwotoc 主要就是解决这个问题。 168 | %{% 169 | %\caption{#1} \gdef\tablename{Table} 170 | %\\ %[-3.5ex] 171 | %\caption{#2} 172 | %\gdef\tablename{表}\\ %[-1.5ex] 173 | %} 174 | 175 | %%%---公式中符号描述----start---- 176 | %\begin{formulasymb}{式中}{-3pt}%-3pt,-20pt调与上方的间距。 177 | % \fdesfirst{第一标签}{控制控制控制控制控制} 178 | % \fdes{其他标签}{控制控制控制控制控制} 179 | %\end{formulasymb} 180 | \newenvironment{formulades}[1]% 181 | {\noindent\begin{list}{}{% 182 | \setlength\topsep{0pt} 183 | \settowidth{\labelwidth}{#1} 184 | \setlength{\labelsep}{1mm} 185 | \setlength{\leftmargin}{\labelwidth+\labelsep} 186 | }}{\end{list}} 187 | \newenvironment{formulasymb}[2]%-\!-\!-\!- 188 | {\vspace*{#2}\newcommand{\fdesfirst}[2]% 189 | {\begin{formulades}{#1\hspace*{26pt}##1~\cdash}\item[#1\hspace*{26pt}##1~\cdash]{##2}\end{formulades}\vspace*{-21pt}}%自己调距 190 | \newcommand{\fdes}[2]{\begin{formulades}{#1\hspace{26pt}##1~\cdash}\item[##1~\cdash]{##2}\end{formulades}\vspace*{-21pt}}}%自己调距 191 | {\vspace{21pt}\relax}%21pt调距 192 | %%----公式中符号描述----end----- 193 | 194 | %% ---- 左对齐的公式 start----- \begin{flualign} a=c \end{flualign} 195 | \newenvironment{flualign}{% 196 | \@fleqntrue 197 | \@mathmargin = -1sp 198 | \@mathmargin\leftmargini minus\leftmargini 199 | \let\mathindent=\@mathmargin 200 | \start@align\@ne\st@rredfalse\m@ne 201 | }{% 202 | \math@cr \black@\totwidth@ 203 | \egroup 204 | \ifingather@ 205 | \restorealignstate@ 206 | \egroup 207 | \nonumber 208 | \ifnum0=`{\fi\iffalse}\fi 209 | \else 210 | $$% 211 | \fi 212 | \ignorespacesafterend 213 | \@fleqnfalse 214 | } 215 | %% ---- 左对齐的公式 end---- 216 | 217 | %重新定义BiChapter命令,可实现标题手动换行,但不影响目录 218 | \def\BiChapter{\relax\@ifnextchar [{\@BiChapter}{\@@BiChapter}} 219 | \def\@BiChapter[#1]#2#3{\chapter[#1]{#2} 220 | \addcontentsline{toe}{chapter}{\bfseries \xiaosi Chapter \thechapter\hspace{0.5em} #3}} 221 | \def\@@BiChapter#1#2{\chapter{#1} 222 | \addcontentsline{toe}{chapter}{\bfseries \xiaosi Chapter \thechapter\hspace{0.5em}{\boldmath #2}}} 223 | %\newcommand{\BiChapter}[2] 224 | %{ 225 | % \chapter{#1} 226 | % \addcontentsline{toe}{chapter}{\bfseries Chapter \thechapter\hspace{0.5em} #2} 227 | %} 228 | 229 | \newcommand{\BiSection}[2] 230 | { \section{#1} 231 | \addcontentsline{toe}{section}{\protect\numberline{\csname thesection\endcsname}#2} 232 | } 233 | 234 | \newcommand{\BiSubsection}[2] 235 | { \subsection{#1} 236 | \addcontentsline{toe}{subsection}{\protect\numberline{\csname thesubsection\endcsname}#2} 237 | } 238 | 239 | \newcommand{\BiSubsubsection}[2] 240 | { \subsubsection{#1} 241 | \addcontentsline{toe}{subsubsection}{\protect\numberline{\csname thesubsubsection\endcsname}#2} 242 | } 243 | 244 | \newcommand{\BiAppendixChapter}[2] % 该附录命令适用于发表文章,简历等 245 | {\phantomsection 246 | \markboth{#1}{#1}%\markboth{\MakeUppercase{#1}}{\MakeUppercase{#1}} 247 | \addcontentsline{toc}{chapter}{\hei #1} 248 | \addcontentsline{toe}{chapter}{\bfseries \xiaosi #2} \chapter*{#1} 249 | } 250 | 251 | \newcommand{\BiAppChapter}[2] % 该附录命令适用于有章节的完整附录 252 | {\phantomsection \chapter{#1} %\markboth{\MakeUppercase{#1}}{\MakeUppercase{#1}} %为了winedt中project tree中toc正确显示,不要挪到下一行; 253 | %\addcontentsline{toc}{chapter}{\hei #1} 254 | \addcontentsline{toe}{chapter}{\bfseries \xiaosi Appendix \thechapter~~#2} 255 | } 256 | 257 | \renewcommand{\thefigure}{\arabic{chapter}-\arabic{figure}}%使图编号为 7-1 的格式 %\protect{~} 258 | %\renewcommand\fnum@figure{\figurename\nobreakspace\thefigure\protect{~~~~~~~~~}} % 259 | 260 | \renewcommand{\thesubfigure}{\alph{subfigure})}%使子图编号为 a)的格式 261 | \renewcommand{\p@subfigure}{\thefigure ~~} %%使子图引用为 7-1 a) 的格式,母图编号和子图编号之间用~~加一个空格 262 | %\renewcommand{\thesubfigure}{\alph{subfigure}} 263 | %\renewcommand{\p@subfigure}{\thefigure} %%使子图引用为 7-1a 的格式 264 | %\renewcommand{\@thesubfigure}{\thesubfigure)\hskip\subfiglabelskip}%使子图编号为 a)的格式 265 | 266 | \renewcommand{\thetable}{\arabic{chapter}-\arabic{table}}%%使表编号为 7-1 的格式 267 | \renewcommand{\theequation}{\arabic{chapter}-\arabic{equation}}%%使公式编号为 7-1 的格式 268 | 269 | %----------- 设置算法标题形式,由“Algorithm 2.1:算法标题” 改为“算法 2-1 算法标题”,并且定义算法的双标题命令;---------% 270 | 271 | \newcommand{\algoenname}{Algo.} %算法英文标题 272 | \newcommand{\listalgoenname}{List of Algorithms} 273 | \newfloatlist[chapter]{algoen}{aen}{\listalgoenname}{\algoenname} 274 | \newfixedcaption{\algoencaption}{algoen} 275 | \renewcommand{\thealgoen}{\thechapter-\arabic{algocf}} 276 | \renewcommand{\@cftmakeaentitle}{\chapter*{\listalgoenname\@mkboth{\bfseries\listalgoenname}{\bfseries\listalgoenname}}} 277 | 278 | \renewcommand{\algorithmcfname}{算法} 279 | \setlength\AlCapSkip{1.2ex} 280 | \SetAlgoSkip{1pt} 281 | \renewcommand{\algocf@captiontext}[2]{\wuhao#1\algocf@typo ~ \AlCapFnt{}#2} % text of caption 282 | \expandafter\ifx\csname algocf@within\endcsname\relax% if \algocf@within doesn't exist 283 | \renewcommand\thealgocf{\@arabic\c@algocf} % and the way it is printed 284 | \else% else 285 | \renewcommand\thealgocf{\csname the\algocf@within\endcsname-\@arabic\c@algocf} 286 | \fi 287 | \renewcommand{\algocf@makecaption}[2]{%中英文双标题一定多于一行,因此去掉单行时的判断,并将\parbox中标题设置为居中 288 | \addtolength{\hsize}{\algomargin}% 289 | \sbox\@tempboxa{\algocf@captiontext{#1}{#2}}% 290 | \hskip .5\algomargin% 291 | \parbox[t]{\hsize}{\centering\algocf@captiontext{#1}{#2}}% 292 | \addtolength{\hsize}{-\algomargin}% 293 | } 294 | \newcommand{\AlgoBiCaption}[2]{%直接取出自定义的中英文标题条目加入到真正的\caption 中 295 | \caption[#1]{\protect\setlength{\baselineskip}{1.5em}#1 \protect \\ Algo. \thealgocf~~ #2} % \algoencaption{#2} 296 | \addcontentsline{aen}{algoen}{\protect\numberline{\thealgoen}{#2}} 297 | } 298 | \renewcommand{\cftalgoendotsep}{1} %算法的英文目录里的点的间距 299 | 300 | \makeatother 301 | %定义 学科 学位 302 | \def \xuekeEngineering {Engineering} 303 | \def \xuekeScience {Science} 304 | \def \xuekeManagement {Management} 305 | \def \xuekeArts {Arts} 306 | 307 | \ifx \xueke \xuekeEngineering 308 | \newcommand{\cxueke}{工学} 309 | \newcommand{\exueke}{Engineering} 310 | \fi 311 | 312 | \ifx \xueke \xuekeScience 313 | \newcommand{\cxueke}{理学} 314 | \newcommand{\exueke}{Science} 315 | \fi 316 | 317 | \ifx \xueke \xuekeManagement 318 | \newcommand{\cxueke}{管理学} 319 | \newcommand{\exueke}{Management} 320 | \fi 321 | 322 | \ifx \xueke \xuekeArts 323 | \newcommand{\cxueke}{文学} 324 | \newcommand{\exueke}{Arts} 325 | \fi 326 | 327 | \newcommand{\cdash}{\mbox{—\!\!\!\!—\!\!\!\!—}}%输入中文破折号的命令 328 | \newcommand{\dif}{\mathrm{d}}%在数学模式中输入微分dx 329 | 330 | %%% Local Variables: 331 | %%% mode: latex 332 | %%% TeX-master: "../main" 333 | %%% End: 334 | -------------------------------------------------------------------------------- /setup/auto/Definition.el: -------------------------------------------------------------------------------- 1 | (TeX-add-style-hook "Definition" 2 | (lambda () 3 | (LaTeX-add-environments 4 | '("formulasymb" 2) 5 | '("formulades" 1) 6 | "flualign") 7 | (TeX-add-symbols 8 | '("BiAppChapter" 2) 9 | '("BiAppendixChapter" 2) 10 | '("BiSubsubsection" 2) 11 | '("BiSubsection" 2) 12 | '("BiSection" 2) 13 | '("fdes" 2) 14 | '("fdesfirst" 2) 15 | '("LTBiTocCaption" 5) 16 | '("TableBiCaption" 2) 17 | '("SubfigEnCaption" 1) 18 | '("FigureBiCaption" 2) 19 | '("mr" 1) 20 | "song" 21 | "fs" 22 | "kai" 23 | "hei" 24 | "li" 25 | "yihao" 26 | "erhao" 27 | "xiaoer" 28 | "sanhao" 29 | "xiaosan" 30 | "sihao" 31 | "banxiaosi" 32 | "xiaosi" 33 | "dawuhao" 34 | "wuhao" 35 | "xiaowu" 36 | "banbanxiaosi" 37 | "subfigencaptionlist" 38 | "figenname" 39 | "listfigenname" 40 | "tblenname" 41 | "listtblenname" 42 | "cxueke" 43 | "exueke" 44 | "cdash" 45 | "dif" 46 | "temp" 47 | "hittemp" 48 | "tablename" 49 | "mathindent" 50 | "BiChapter"))) 51 | 52 | -------------------------------------------------------------------------------- /setup/auto/package.el: -------------------------------------------------------------------------------- 1 | (TeX-add-style-hook "package" 2 | (lambda () 3 | (TeX-add-symbols 4 | "atemp"))) 5 | 6 | -------------------------------------------------------------------------------- /setup/figtab.tex: -------------------------------------------------------------------------------- 1 | % -*-coding: utf-8 -*- 2 | 3 | %% 中英文插图、表格、算法索引 4 | %% 硕博士学位论文规范均不要求这一项,请正式打印的时候在main.tex中屏蔽掉\input{figtab.tex}; 5 | 6 | \ifxueweidoctor 7 | %\clearpage{\pagestyle{empty}\cleardoublepage} % 清除目录后面空页的页眉和页脚 8 | \else% 9 | {\ifoneortwoside\clearpage{\pagestyle{empty}\cleardoublepage}\else\newpage\fi} % 清除目录后面空页的页眉和页脚 10 | \fi 11 | 12 | \addcontentsline{toc}{chapter}{\hei 插~~~~图} % 中文插图加入到中文目录 13 | \listoffigures % 生成中文 图形索引 14 | 15 | \ifxueweidoctor %硕士学位论文没有英文目录 16 | %\clearpage{\pagestyle{empty}\cleardoublepage} % 英文图形索引 右开 ?需要吗? 17 | \pdfbookmark[0]{List of Figures}{listfigure} 18 | \addcontentsline{toe}{chapter}{\bfseries\xiaosi List of Figures} % 英文插图加入到英文目录 19 | \listoffigen % 生成英文图索引 20 | \fi 21 | 22 | \ifxueweidoctor 23 | %\clearpage{\pagestyle{empty}\cleardoublepage} % 清除目录后面空页的页眉和页脚 24 | \else% 25 | {\ifoneortwoside\clearpage{\pagestyle{empty}\cleardoublepage}\else\newpage\fi} % 清除目录后面空页的页眉和页脚 26 | \fi 27 | 28 | \addcontentsline{toc}{chapter}{\hei 表~~~~格} % 中文表格加入到中文目录 29 | \listoftables % 生成中文 表格索引 30 | 31 | \ifxueweidoctor %硕士学位论文没有英文目录 32 | %\clearpage{\pagestyle{empty}\cleardoublepage} % 英文表格索引 右开 ?需要吗? 33 | \addcontentsline{toe}{chapter}{\bfseries\xiaosi List of Tables} % 英文表格加入到英文目录 34 | \pdfbookmark[0]{List of Tables}{listtable} 35 | \listoftblen % 生成英文 表格索引 36 | \fi 37 | %% 如果不需要图表索引,注释掉上面的即可 38 | 39 | \ifxueweidoctor 40 | %\clearpage{\pagestyle{empty}\cleardoublepage} % 清除目录后面空页的页眉和页脚 41 | \else% 42 | {\ifoneortwoside\clearpage{\pagestyle{empty}\cleardoublepage}\else\newpage\fi} % 清除目录后面空页的页眉和页脚 43 | \fi 44 | 45 | \addcontentsline{toc}{chapter}{\hei 算~~~~法} % 中文算法加入到中文目录 46 | \renewcommand{\listalgorithmcfname}{算~~~~法} %中文“算法”代替英文list of algorithms 47 | \listofalgorithms % 生成中文算法索引 48 | 49 | \ifxueweidoctor %硕士学位论文没有英文目录 50 | %\clearpage{\pagestyle{empty}\cleardoublepage} % 英文算法索引 右开 ?需要吗? 51 | \addcontentsline{toe}{chapter}{\bfseries\xiaosi List of Algorithms} % 英文算法加入到英文目录 52 | \pdfbookmark[0]{List of Algorithms}{listAlgo} 53 | \listofalgoen % 生成英文 表格索引 54 | \fi 55 | 56 | 57 | %%% Local Variables: 58 | %%% mode: latex 59 | %%% TeX-master: "../main" 60 | %%% End: 61 | -------------------------------------------------------------------------------- /setup/format.tex: -------------------------------------------------------------------------------- 1 | % -*-coding: utf-8 -*- 2 | 3 | %论文版芯大小一般应为150mm×220mm(包括页眉及页码则为150mm×240mm) 4 | %页码在版芯下边线之下隔行居中放置; 5 | %% 左右 6 | \setlength{\textwidth}{15cm} 7 | \setlength{\oddsidemargin}{0.46cm} % 左边 3cm=0.46+2.54 8 | \setlength{\evensidemargin}{0.46cm} 9 | % 上下 10 | \setlength{\topmargin}{0.42cm} % 3.3=2.54+0.76 11 | \setlength{\headheight}{0.80cm} % 0.8 12 | \setlength{\headsep}{0.40cm} % 0.4 13 | \setlength{\textheight}{22.0cm} % 22.0 14 | \setlength{\footskip}{1.1cm} %1.1 15 | 16 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 17 | %允许公式换页显示,否则大型推导公式都在一页内, 18 | %一页显示不下放到第二页,导致很大的空白空间,很不好看 19 | \allowdisplaybreaks[4] 20 | 21 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 22 | %下面这组命令使浮动对象的缺省值稍微宽松一点,从而防止幅度 23 | %对象占据过多的文本页面,也可以防止在很大空白的浮动页上放置很小的图形。 24 | \renewcommand{\topfraction}{0.9999999} 25 | \renewcommand{\textfraction}{0.0000001} 26 | \renewcommand{\floatpagefraction}{0.9999} 27 | 28 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 29 | % 重定义一些正文相关标题 30 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 31 | \theoremstyle{plain} \theorembodyfont{\song\rmfamily} 32 | \theoremheaderfont{\hei\rmfamily} %\theoremseparator{:} 33 | \newtheorem{definition}{\hei 定义}[chapter] 34 | \newtheorem{example}{\hei 例}[chapter] 35 | \newtheorem{algo}{\hei 算法}[chapter] 36 | \newtheorem{theorem}{\hei 定理}[chapter] 37 | \newtheorem{axiom}{\hei 公理}[chapter] 38 | \newtheorem{proposition}{\hei 命题}[chapter] 39 | \newtheorem{lemma}{\hei 引理}[chapter] 40 | \newtheorem{corollary}{\hei 推论}[chapter] 41 | \newtheorem{remark}{\hei 注解}[chapter] 42 | %\newtheorem{proposition}[definition]{\hei 命题} 43 | %\newtheorem{lemma}[definition]{\hei 引理} 44 | %\newtheorem{exercise}[definition]{} 45 | %\newtheorem{corollary}[definition]{\hei 推论} 46 | %\newtheorem{remark}[definition]{\hei 注解} 47 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 48 | %解决原proof定理环境的两个问题: 49 | % 1. proof 中的item缩进不对 50 | % 2. proof 中的最后一个公式下出现一个黑方块。 51 | %\theoremsymbol{$\blacksquare$} 52 | %\newtheorem{proof}{\hei 证明} 53 | \newenvironment{proof}{\noindent{\hei 证明:}}{\hfill $ \square $ \vskip 4mm} 54 | \theoremsymbol{$\square$} 55 | 56 | 57 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 58 | % 用于中文段落缩进 和正文版式 59 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 60 | 61 | \ifx\atempxetex\usewhat 62 | \newcommand{\CJKcaption}[1]{ 63 | \ifx\CJK@actualBinding \@empty 64 | \PackageError{CJK}{ 65 | You must be inside of a CJK environment to use \protect\CJKcaption}{} 66 | \else 67 | \makeatletter 68 | \InputIfFileExists{#1.cpx}{}{ 69 | \PackageError{CJK}{ 70 | Can't find #1.cpx}{ 71 | The default captions are used if you continue.}} 72 | \makeatother 73 | \fi} 74 | \CJKcaption{gb_452_UTF8} 75 | \else 76 | \CJKcaption{gb_452_UTF8} %_UTF8 77 | \newlength \CJKtwospaces 78 | \def\CJKindent{ 79 | \settowidth\CJKtwospaces{\CJKchar{"0A1}{"0A1}\CJKchar{"0A1}{"0A1}}% 80 | \parindent\CJKtwospaces 81 | } 82 | %\CJKtilde \CJKindent 83 | \fi 84 | 85 | \setlength{\parindent}{26pt} %由于工大论文的每行的字距加大了,需要增加段首缩2pt 86 | 87 | \renewcommand\contentsname{\hei 目~~~~录} 88 | 89 | %%%%%%章节标题为“第1章”的形式 90 | \renewcommand\chaptername{\CJKprechaptername~\thechapter~\CJKchaptername} 91 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 92 | %定义段落章节的标题和目录项的格式 93 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 94 | \setcounter{secnumdepth}{4} \setcounter{tocdepth}{2} 95 | 96 | \titleformat{\chapter}[block]{\xiaoer\bf\filcenter\hei\sf\boldmath}{\xiaoer\chaptertitlename}{18pt}{\xiaoer} 97 | % \titlespacing{\chapter}{0pt}{8pt}{16pt} %block为居中对齐,hang 为悬挂的居中对齐(不包括 98 | 99 | \titleformat{\section}[hang]{\hei\sf\xiaosan\boldmath}{\xiaosan\thesection}{0.5em}{} 100 | % \titlespacing{\section}{0pt}{13pt}{13pt} 101 | 102 | \titleformat{\subsection}[hang]{\hei\sf\sihao\boldmath}{\sihao\thesubsection}{0.5em}{} 103 | % \titlespacing{\subsection}{0pt}{8pt}{7pt} 104 | 105 | \titleformat{\subsubsection}[hang]{\hei\sf\xiaosi\boldmath}{\thesubsubsection}{0.5em}{} %[\;\;] 106 | % \titlespacing{\subsubsection}{0pt}{3pt}{2pt} 107 | 108 | % 章节前后的间距细调, 109 | % 由genfazhan根据研究生院老师的审查后,与word示例范文相比细调确定 110 | \titlespacing{\chapter}{0pt}{0mm}{6mm} %(生成的前距约12mm,后距约10mm,范例中前后距都是10mm,我调不出来,不过12mm和10mm,差不多,看不出来,应该没问题) 111 | \titlespacing{\section}{0pt}{4mm}{4mm} %(生成的前距约7-8mm) 112 | \titlespacing{\subsection}{0pt}{3mm}{3mm} %(生成的前距约6-7mm) 113 | \titlespacing{\subsubsection}{0pt}{2mm}{2mm} % 114 | 115 | % 按工大标准, 缩小目录中各级标题之间的缩进,使它们相隔一个字符距离,也就是12pt 116 | \makeatletter 117 | \renewcommand*\l@chapter{\@dottedtocline{0}{0em}{4.84em}}%控制英文目录: 细点\@dottedtocline 粗点\@dottedtoclinebold 118 | \renewcommand*\l@section{\@dottedtocline{1}{12pt}{18pt}} 119 | \renewcommand*\l@subsection{\@dottedtocline{2}{24pt}{27pt}} 120 | \renewcommand*\l@subsubsection{\@dottedtocline{3}{36pt}{39pt}} 121 | \renewcommand*\l@paragraph{\@dottedtocline{4}{48pt}{48pt}} 122 | \renewcommand*\l@subparagraph{\@dottedtocline{5}{60pt}{60pt}} 123 | % 英文目录中章标题对应的点号及相应页码为黑体 124 | \def\@dottedtoclinebold#1#2#3#4#5{% 125 | \ifnum #1>\c@tocdepth \else 126 | \vskip \z@ \@plus.2\p@ 127 | {\leftskip #2\relax \rightskip \@tocrmarg \parfillskip -\rightskip 128 | \parindent #2\relax\@afterindenttrue 129 | \interlinepenalty\@M 130 | \leavevmode 131 | \@tempdima #3\relax 132 | \advance\leftskip \@tempdima \null\nobreak\hskip -\leftskip 133 | {#4}\nobreak 134 | \leaders\hbox{$\m@th 135 | \mkern \@dotsep mu\hbox{\ifnum1=#1 \bf\fi.}\mkern \@dotsep 136 | mu$}\hfill 137 | \nobreak 138 | \hb@xt@\@pnumwidth{\hfil \normalfont \normalcolor \ifnum1=#1 \bf\fi#5}%目录层为1时,页码粗体 139 | \par}% 140 | \fi} 141 | %控制中文目录 142 | %\dottedcontents{chapter}[3.4em]{\vspace{0.5em}\hspace{-3.4em}\hei \bf\boldmath}{0.0em}{5pt}% 章标题后用粗点 143 | \titlecontents{chapter}[3.92em]{\vspace{0.5em}\hspace{-3.92em}\hei \bf\boldmath}{\contentslabel{0em}}{\hspace*{-0em}}{\normalfont\titlerule*[5pt]{.}\contentspage} %章标题后用细点 144 | \dottedcontents{section}[1.16cm]{}{1.8em}{5pt} 145 | \dottedcontents{subsection}[2.00cm]{}{2.7em}{5pt} 146 | \dottedcontents{subsubsection}[2.86cm]{}{3.4em}{5pt} 147 | 148 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 149 | % 定义页眉和页脚 使用fancyhdr 宏包 150 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 151 | \newcommand{\makeheadrule}{% 152 | \makebox[-3pt][l]{\rule[.7\baselineskip]{\headwidth}{0.4pt}} 153 | \rule[0.85\baselineskip]{\headwidth}{2.25pt}\vskip-.8\baselineskip} 154 | \renewcommand{\headrule}{% 155 | {\if@fancyplain\let\headrulewidth\plainheadrulewidth\fi 156 | \makeheadrule}} 157 | 158 | \pagestyle{fancyplain} 159 | 160 | %去掉章节标题中的数字 161 | %%不要注销这一行,否则页眉会变成:“第1章1 绪论”样式 162 | \renewcommand{\chaptermark}[1]{\markboth{\chaptertitlename~~ \ #1}{}} 163 | \fancyhf{} 164 | 165 | %在book文件类别下,\leftmark自动存录各章之章名,\rightmark记录节标题 166 | %% 页眉字号 工大要求 小五 167 | %根据单双面打印设置不同的页眉; 168 | \ifoneortwoside 169 | \fancyhead[CO]{\song \xiaowu\leftmark} 170 | \fancyhead[CE]{\song \xiaowu\leftmark} 171 | %\fancyhead[CE]{\song \xiaowu 哈尔滨工业大学\cxueke\cxuewei 学位论文 }% 172 | \fancyfoot[C,C]{\xiaowu --~\thepage~--} %\if@mainmatter \fi 173 | \else% 174 | \fancyhead[CO]{\song \xiaowu 哈尔滨工业大学\cxueke\cxuewei 学位论文} 175 | \fancyhead[CE]{\song \xiaowu 哈尔滨工业大学\cxueke\cxuewei 学位论文}% 176 | \fancyfoot[C,C]{\xiaowu --~\thepage~--} %\if@mainmatter \fi 177 | \fi 178 | 179 | \renewcommand\frontmatter{% 180 | \cleardoublepage 181 | \@mainmatterfalse 182 | \pagenumbering{Roman}} 183 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 184 | % 设置行距和段落间垂直距离 185 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 186 | \renewcommand{\CJKglue}{\hskip 0.3pt plus 0.08\baselineskip}%加大字间距,使每行33个字 187 | %\setlength{\belowcaptionskip}{10pt} % 加大标题和表格之间的距离 \abovecaptionskip 默认是10pt 188 | %\setlength{\parskip}{3pt plus1pt minus1pt} % 段落之间的竖直距离 189 | \setlength{\parskip}{1.5pt plus 1pt minus 1pt} % by genfazhan(本来想改成0pt,和正常段之间一致,但生成的目录有点太紧凑了,不太好看,所以就设成了1.5pt) 190 | \renewcommand{\baselinestretch}{1.2}% 定义行距 191 | 192 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 193 | % 调整列表环境的垂直间距 194 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 195 | \setitemize{itemindent=38pt,leftmargin=0pt,itemsep=-0.4ex,listparindent=26pt,partopsep=0pt,parsep=0.5ex,topsep=-0.25ex} 196 | \setenumerate{itemindent=38pt,leftmargin=0pt,itemsep=-0.4ex,listparindent=26pt,partopsep=0pt,parsep=0.5ex,topsep=-0.25ex} 197 | \setdescription{itemindent=38pt,leftmargin=0pt,itemsep=-0.4ex,listparindent=26pt,partopsep=0pt,parsep=0.5ex,topsep=-0.25ex} 198 | 199 | 200 | \renewcommand\@biblabel[1]{#1\hspace{0.5em}} %去除参考文献里标号两边的括号 201 | \newcommand{\ucite}[1]{$^{\mbox{\scriptsize \cite{#1}}}$} % 增加 \ucite 命令使显示的引用为上标形式 202 | \newcommand{\citeup}[1]{$^{\mbox{\scriptsize \cite{#1}}}$} % for WinEdt users 203 | 204 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 205 | % 定制浮动图形和表格标题样式 %这里用ccaption完全代替了caption2的功能 206 | \captionstyle{\centering} %不同的图标题形式采用不同的命令 207 | %\indentcaption{0pt} %参见ccaption 208 | \hangcaption 209 | \captionnamefont{\song \rmfamily\wuhao\selectfont} 210 | \captiontitlefont{\song \rmfamily\wuhao\selectfont} 211 | \captiondelim{~} %~ 212 | 213 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 214 | % 定义题头格言的格式 215 | % 用法 \begin{Aphorism}{author} 216 | % aphorism 217 | % \end{Aphorism} 218 | \newsavebox{\AphorismAuthor} 219 | \newenvironment{Aphorism}[1] 220 | {\vspace{0.5cm}\begin{sloppypar} \slshape 221 | \sbox{\AphorismAuthor}{#1} 222 | \begin{quote}\small\itshape } 223 | {\\ \hspace*{\fill}------\hspace{0.2cm} \usebox{\AphorismAuthor} 224 | \end{quote} 225 | \end{sloppypar}\vspace{0.5cm}} 226 | 227 | %自定义一个空命令,用于注释掉文本中不需要的部分。 228 | \newcommand{\comment}[1]{} 229 | 230 | \renewcommand\contentsname{\hei 目~~~~录} 231 | \renewcommand\listfigurename{\hei 插~~~~图} 232 | \renewcommand\listtablename{\hei 表~~~~格} 233 | 234 | %%%%%%将章标题中的中文数字(一、二、三)变为阿拉伯数字(1,2,3) 235 | \renewcommand\CJKthechapter{%\CJKnumber 236 | {\@arabic\c@chapter}} 237 | 238 | %%%%%%不要拉大行距使得页面充满 239 | \raggedbottom 240 | 241 | % This is the flag for longer version 242 | \newcommand{\longer}[2]{#1} 243 | 244 | \newcommand{\ds}{\displaystyle} 245 | 246 | % define graph scale 247 | \def\gs{1.0} 248 | 249 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 250 | % 自定义项目列表标签及格式 \begin{hitlist} 列表项 \end{hitlist} 251 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 252 | \newcounter{hitctr} %自定义新计数器 253 | \newenvironment{hitlist}{%%%%%定义新环境 254 | \begin{list}{{\hei (\arabic{hitctr})}} %%标签格式 255 | { 256 | \usecounter{hitctr} 257 | \setlength{\leftmargin}{0cm} %左边界 258 | \setlength{\parsep}{0ex} %段落间距 259 | \setlength{\topsep}{0pt} %列表到上下文的垂直距离 260 | \setlength{\itemsep}{0ex} %标签间距 261 | \setlength{\labelsep}{0.3em} %标号和列表项之间的距离,默认0.5em 262 | \setlength{\itemindent}{46pt} %标签缩进量 263 | \setlength{\listparindent}{27pt} %段落缩进量 264 | }} 265 | {\end{list}}%%%%% 266 | 267 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 268 | % 自定义项目列表标签及格式 \begin{publist} 列表项 \end{publist} 269 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 270 | \newcounter{pubctr} %自定义新计数器 271 | \newenvironment{publist}{%%%%%定义新环境 272 | \begin{list}{\arabic{pubctr}} %%标签格式 273 | { 274 | \usecounter{pubctr} 275 | \setlength{\leftmargin}{2em} % 左边界 \leftmargin =\itemindent + \labelwidth + \labelsep 276 | \setlength{\itemindent}{0em} % 标号缩进量 277 | \setlength{\labelwidth}{1em} % 标号宽度 278 | \setlength{\labelsep}{1em} % 标号和列表项之间的距离,默认0.5em 279 | \setlength{\rightmargin}{0em} % 右边界 280 | \setlength{\topsep}{0ex} % 列表到上下文的垂直距离 281 | % \setlength{\partopsep}{0ex} % 列表是一个新的段落时,加的额外到上下文的距离 282 | \setlength{\parsep}{0ex} % 段落间距 283 | \setlength{\itemsep}{0ex} % 标签间距 284 | \setlength{\listparindent}{26pt} % 段落缩进量 285 | }} 286 | {\end{list}}%%%%% 287 | 288 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 289 | % 默认字体 290 | \renewcommand\normalsize{% 291 | \@setfontsize\normalsize{12pt}{13pt} 292 | %\setlength\abovedisplayskip{8pt plus 2pt minus 2pt} 293 | %\setlength\abovedisplayshortskip{7pt plus 2pt minus 2pt} 294 | \setlength\abovedisplayskip{5pt plus 2pt minus 2pt} %by gengfazhan 295 | \setlength\abovedisplayshortskip{4pt plus 2pt minus 2pt} %by gengfazhan(生成的公式和正文距离减小了,比正常行距稍大一些) 296 | \setlength\belowdisplayskip{\abovedisplayskip} 297 | \setlength\belowdisplayshortskip{\abovedisplayshortskip} 298 | \setlength\jot{6pt} 299 | \let\@listi\@listI} 300 | \def\defaultfont{\renewcommand{\baselinestretch}{1.5}\normalsize\selectfont} %正文行间距,大致与word中小四宋体的1.25倍行距相同,使用者若不满意可精调此参数 301 | \predisplaypenalty=0 %公式之前可以换页,公式出现在页面顶部 302 | 303 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 304 | % 封面、摘要、版权、致谢格式定义 305 | \def\ctitle#1{\def\@ctitle{#1}}\def\@ctitle{} 306 | \def\cdegree#1{\def\@cdegree{#1}}\def\@cdegree{} 307 | \def\caffil#1{\def\@caffil{#1}}\def\@caffil{} 308 | \def\csubject#1{\def\@csubject{#1}}\def\@csubject{} 309 | \def\cauthor#1{\def\@cauthor{#1}}\def\@cauthor{} 310 | \def\csupervisor#1{\def\@csupervisor{#1}}\def\@csupervisor{} 311 | \def\cassosupervisor#1{\def\@cassosupervisor{~ & {\hei 副 \hfill 导 \hfill 师:} & #1\\}}\def\@cassosupervisor{} 312 | \def\ccosupervisor#1{\def\@ccosupervisor{~ & {\hei 联 \hfill 合\hfill 导 \hfill 师:} & #1\\}}\def\@ccosupervisor{} 313 | \def\cdate#1{\def\@cdate{#1}}\def\@cdate{} 314 | \long\def\cabstract#1{\long\def\@cabstract{#1}}\long\def\@cabstract{} 315 | \def\ckeywords#1{\def\@ckeywords{#1}}\def\@ckeywords{} 316 | 317 | \def\etitle#1{\def\@etitle{#1}}\def\@etitle{} 318 | \def\edegree#1{\def\@edegree{#1}}\def\@edegree{} 319 | \def\eaffil#1{\def\@eaffil{#1}}\def\@eaffil{} 320 | \def\esubject#1{\def\@esubject{#1}}\def\@esubject{} 321 | \def\eauthor#1{\def\@eauthor{#1}}\def\@eauthor{} 322 | \def\esupervisor#1{\def\@esupervisor{#1}}\def\@esupervisor{} 323 | %\def\eassosupervisor#1{\def\@eassosupervisor{#1}}\def\@eassosupervisor{} 324 | \def\eassosupervisor#1{\def\@eassosupervisor{~ & \textbf{Associate Supervisor:} & #1\\}}\def\@eassosupervisor{} 325 | %\def\ecosupervisor#1{\def\@ecosupervisor{#1}}\def\@ecosupervisor{} 326 | \def\ecosupervisor#1{\def\@ecosupervisor{~ & \textbf{Co Supervisor:} & #1\\}}\def\@ecosupervisor{} 327 | \def\edate#1{\def\@edate{#1}}\def\@edate{} 328 | \long\def\eabstract#1{\long\def\@eabstract{#1}}\long\def\@eabstract{} 329 | \long\def\NotationList#1{\long\def\@NotationList{#1}}\long\def\@NotationList{} 330 | \def\ekeywords#1{\def\@ekeywords{#1}}\def\@ekeywords{} 331 | \def\natclassifiedindex#1{\def\@natclassifiedindex{#1}}\def\@natclassifiedindex{} 332 | \def\internatclassifiedindex#1{\def\@internatclassifiedindex{#1}}\def\@internatclassifiedindex{} 333 | \def\statesecrets#1{\def\@statesecrets{#1}}\def\@statesecrets{} 334 | 335 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 336 | % 定义封面 337 | \def\makecover{ 338 | \normalbiao %表格字号设置 339 | \begin{titlepage} 340 | 341 | % 封面一 342 | \begin{center} 343 | 344 | % \parbox[t][1cm][b]{\textwidth}{\xiaoyi 345 | % \begin{center} {\song \cxuewei 学位论文 }\end{center} } %\ifxueweimaster\cxueke\fi 346 | % 347 | % \parbox[t][0.8cm][t]{\textwidth}{ 348 | % \begin{center} \end{center} } 349 | % 350 | % \parbox[t][2cm][t]{\textwidth}{\erhao 351 | % \begin{center} {\hei \@ctitle}\end{center} } 352 | % 353 | % \ifxueweidoctor 354 | % \parbox[t][3.8cm][t]{\textwidth}{\erhao %英文标题太长时可以采用\xiaoer 355 | % \begin{center} {\bfseries \@etitle}\end{center} } 356 | % \else 357 | % \parbox[t][3.8cm][t]{\textwidth}{\centering 358 | % \ } 359 | % \fi 360 | % 361 | % \parbox[t][2.0cm][t]{\textwidth}{\xiaoer 362 | % \begin{center} {\song \@cauthor} \end{center} } 363 | 364 | \ifxueweidoctor 365 | \parbox[t][8.5cm][t]{\textwidth}{\centering 366 | \includegraphics[width = \textwidth]{lspcover1}} 367 | \else 368 | \parbox[t][8.5cm][t]{\textwidth}{\centering 369 | \includegraphics[width = 8cm]{lspcover1}} 370 | \fi 371 | %\includegraphics{lspcover1} 372 | 373 | % \parbox[t][1.2cm][t]{\textwidth}{\xiaoer 374 | % \begin{center} {\kai 哈尔滨工业大学} \end{center} } 375 | % 376 | % \parbox[t][0.5cm][t]{\textwidth}{ 377 | % \begin{center} {\song \xiaoer \@cdate} \end{center} } 378 | 379 | \end{center} 380 | 381 | % % 封二 空白页 382 | % \ifoneortwoside 383 | % \newpage 384 | % ~~~\vspace{1em} 385 | % \thispagestyle{empty} 386 | % \fi 387 | % 388 | % %内封 389 | % \newpage 390 | % \thispagestyle{empty} 391 | % \begin{center} 392 | % \parbox[t][0.6cm][t]{\textwidth}{ 393 | % \begin{center} \end{center}} 394 | % 395 | % % \parbox[t][2.2cm][t]{\textwidth}{ 396 | % % \song \xiaosi 国内图书分类号: \@natclassifiedindex \\ 397 | % % 国际图书分类号: \@internatclassifiedindex } 398 | % \parbox[t][2.2cm][t]{\textwidth}{\song \xiaosi \centering 399 | % \begin{tabular}{>{\raggedleft}p{4cm}>{\raggedright}p{3.5cm}>{\raggedleft}p{3.5cm}>{\raggedright}p{2cm}}%% %% {rlrl} 400 | % 国内图书分类号:& \@natclassifiedindex & 学校代码:& 10213 \tabularnewline 401 | % 国际图书分类号:& \@internatclassifiedindex & ~~ 密级:& 公开 402 | % \end{tabular}} 403 | % 404 | % \parbox[t][2.7cm][b]{\textwidth}{\xiaoer 405 | % \begin{center} {\song \@cdegree 学位论文 }\end{center} } 406 | % 407 | % \setlength{\baselineskip}{1.5\baselineskip} 408 | % \parbox[t][3.0cm][b]{\textwidth}{\erhao 409 | % \begin{center} {\hei \@ctitle}\end{center} } 410 | % 411 | % \parbox[t][4.3cm][t]{\textwidth}{ 412 | % \begin{center} \end{center} } 413 | % 414 | % \parbox[t][6cm][c]{\textwidth}{ {\sihao 415 | % \begin{center} \renewcommand{\arraystretch}{1.5} \song 416 | % \begin{tabular}{lll@{\extracolsep{0em}}l} 417 | % ~ & {\hei \xueweishort \hfill 士\hfill 研究生:} & \@cauthor\\ 418 | % ~ & {\hei 导\hfill 师:} & \@csupervisor\\ 419 | % \@ccosupervisor 420 | % \@cassosupervisor 421 | % ~ & {\hei 申\hfill 请\hspace{1em}学\hfill 位:} & \@cdegree\\ 422 | % ~ & {\hei 学\hfill 科:} & \@csubject\\ 423 | % ~ & {\hei 所\hfill 在\hspace{1em}单\hfill 位:} & \@caffil\\ 424 | % ~ & {\hei 答\hfill 辩\hspace{1em}日\hfill 期:} & \@cdate\\ 425 | % ~ & {\hei 授予学位单位:} & 哈尔滨工业大学 426 | % \end{tabular} \renewcommand{\arraystretch}{1} 427 | % \end{center} } } 428 | % \end{center} 429 | 430 | %%%%%%增加一空白页 431 | % \ifoneortwoside 432 | % \newpage 433 | % ~~~\vspace{1em} 434 | % \thispagestyle{empty} 435 | % \fi 436 | % 437 | % % 英文封面 438 | % \newpage 439 | % \thispagestyle{empty} 440 | % \begin{center} 441 | % \parbox[t][0.6cm][t]{\textwidth}{ 442 | % \begin{center} \end{center}} 443 | % 444 | % \parbox[t][2.2cm][t]{\textwidth}{ 445 | % \xiaosi Classified Index: \@natclassifiedindex \\ 446 | % U.D.C.: \@internatclassifiedindex } 447 | % 448 | % \parbox[t][2.7cm][b]{\textwidth}{\xiaoer 449 | % \begin{center} { Dissertation for the {\exueweier} Degree }\end{center} } %与中文保持一致,删除in {\exueke} 450 | % 451 | % \parbox[t][3.0cm][b]{\textwidth}{\erhao 452 | % \begin{center} { \@etitle}\end{center} } 453 | % 454 | % \parbox[t][4.0cm][t]{\textwidth}{ 455 | % \begin{center} \end{center} } 456 | % 457 | % \parbox[t][6cm][c]{\textwidth}{ {\sihao 458 | % \begin{center} \renewcommand{\arraystretch}{1.5} 459 | % \begin{tabular}{p{0cm}p{14em}p{13.4em}l@{\extracolsep{2em}}l} 460 | % ~ & \textbf{Candidate:} & \@eauthor\\ 461 | % ~ & \textbf{Supervisor:} & \@esupervisor\\ 462 | % \@ecosupervisor 463 | % \@eassosupervisor 464 | % ~ & \textbf{Academic Degree Applied for:} & \@edegree\\ 465 | % ~ & \textbf{Specialty:} & \@esubject\\ 466 | % ~ & \textbf{Affiliation:} & \@eaffil\\ 467 | % ~ & \textbf{Date of Defence:} & \@edate\\ 468 | % ~ & \textbf{Degree-Conferring-Institution:} & Harbin Institute of Technology 469 | % \end{tabular} 470 | % \end{center}}} 471 | % 472 | % \end{center} 473 | \end{titlepage} 474 | % 475 | % %%%%%%增加一空白页 476 | % \ifoneortwoside 477 | % \newpage 478 | % ~~~\vspace{1em} 479 | % \thispagestyle{empty} 480 | % \fi 481 | % %%%%%%%%%%%%%%%%%%% Abstract and keywords %%%%%%%%%%%%%%%%%%%%%%% 482 | % \clearpage \BiAppendixChapter{摘~~~~要}{Abstract (in Chinese)} %不要挪到下一行,生成正确的摘要toc 483 | % \setcounter{page}{1} 484 | % \song \normalsize 485 | % \defaultfont 486 | % \@cabstract 487 | % \vspace{1em} 488 | % 489 | % \hangafter1\hangindent4.28em\noindent 490 | % {\hei 关键词:} \@ckeywords %新规范有了冒号之后,不用再加\quad 空白距离了。 491 | % 492 | % %%%%%%%%%%%%%%%%%%% English Abstract %%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 493 | % \clearpage 494 | % \defaultfont \BiAppendixChapter{\textbf{Abstract}}{Abstract (in English)} %不要挪到下一行,生成正确的摘要toc 495 | % \@eabstract 496 | % \vspace{1em} 497 | % 498 | % \hangafter1\hangindent5.5em\noindent 499 | % {\textbf{Keywords:}} \@ekeywords % 新规范有了冒号之后,不用再加\quad 空白距离了。 500 | % \wuhaobiao %正文表格设置 501 | } %\makecover 502 | 503 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 504 | % 英文目录格式 505 | \def\@dotsep{1} % 定义英文目录的点间距 506 | \setlength\leftmargini {0pt} 507 | \setlength\leftmarginii {0pt} 508 | \setlength\leftmarginiii {0pt} 509 | \setlength\leftmarginiv {0pt} 510 | \setlength\leftmarginv {0pt} 511 | \setlength\leftmarginvi {0pt} 512 | 513 | \def\engcontentsname{\bfseries Contents} 514 | \newcommand\tableofengcontents{% 515 | %\cleardoublepage 516 | \pdfbookmark[0]{Contents}{econtent} 517 | \if@twocolumn 518 | \@restonecoltrue\onecolumn 519 | \else 520 | \@restonecolfalse 521 | \fi \chapter*{\engcontentsname %chapter*上移一行,避免在toc中出现。 522 | \@mkboth{% 523 | \engcontentsname}{\engcontentsname}} 524 | \@starttoc{toe}% 525 | \if@restonecol\twocolumn\fi 526 | } 527 | 528 | \urlstyle{same} %论文中引用的网址的字体默认与正文中字体不一致,这里修正为一致的。 529 | 530 | %主要符号表 \NotationList 531 | \long\def\notation{\clearpage \BiAppendixChapter{主要符号表}{Main Symbol Table}\normalbiao\@NotationList\wuhaobiao} 532 | 533 | %%% 五号字表格设置 start %%%%% 534 | \gdef\tpltable{\relax} 535 | \let\tpltable\longtable 536 | \gdef\wuhaobiao{%五号字 537 | \def\tabular{\wuhao\gdef\@halignto{}\@tabular} 538 | \def\endtabular{\endarray $\egroup} 539 | \def\longtable{\wuhao\tpltable} 540 | \def\endlongtable{\adl@LTlastrow \adl@org@endlongtable} 541 | } 542 | \gdef\normalbiao{%正常字号 543 | \def\tabular{\gdef\@halignto{}\@tabular} 544 | \def\endtabular{\endarray $\egroup} 545 | \def\longtable{\tpltable} 546 | \def\endlongtable{\adl@LTlastrow \adl@org@endlongtable} 547 | } 548 | \wuhaobiao 549 | %%% 五号字表格设置 end %%%%% 550 | %\renewcommand{\arraystretch}{1.4} %表格中行距 ,导致公式 bmatrix 间距增大。 551 | 552 | % 表格与下方间距 553 | \renewcommand\endtable{\vspace{-4mm}\end@float} 554 | % 算法与下方间距 555 | \renewcommand\endalgorithm{\@algocf@finish \ifthenelse {\equal {\algocf@float }{figure}}{\end {figure}}{ 556 | \@algocf@term@caption \ifthenelse {\boolean {algocf@algoH}}{\end {algocf@Here}} 557 | {\end {algocf}}}\@algocf@term\vspace{-5mm}} 558 | \makeatother 559 | -------------------------------------------------------------------------------- /setup/package.tex: -------------------------------------------------------------------------------- 1 | % -*-coding: utf-8 -*- 2 | 3 | % 图形支持宏包 为了使用pdftex 需要作相应判断 4 | \usepackage{etex}%增加计数器总数(原来是256,宏包多,可能不够用),编译需基于eTeX 5 | \usepackage{ifpdf} 6 | %定义一个新判断命令 %有一个宏包ifpdf 可以完成这件事,应该比这个严谨 7 | %\newif\ifpdf 8 | %\ifx\pdfoutput\undefined 9 | % \pdffalse 10 | %\else 11 | % \pdfoutput=1 12 | % \pdftrue 13 | %\fi 14 | 15 | %%%%%%%%彩色引用和书签%%%%%% 16 | \ifx\atempxetex\usewhat 17 | \usepackage[dvipdfm]{graphicx} 18 | \else 19 | \ifpdf 20 | \usepackage[pdftex]{graphicx} 21 | \else 22 | \usepackage[dvips]{graphicx} 23 | \fi 24 | \fi 25 | 26 | \usepackage[%paperwidth=18.4cm, paperheight= 26cm, % 版面控制宏包,定义规定的版面尺寸 27 | body={15true cm,22true cm}, %论文版芯145mm×210mm(包括页眉及页码则为15mm×240mm) 28 | twosideshift=0 pt, %页码在版芯下边线之下隔行居中放置; 29 | %headheight=1.0true cm 30 | ]{geometry} 31 | \usepackage{layouts} % 打印当前页面格式的宏包 32 | \usepackage[sf]{titlesec} % 控制标题的宏包 33 | \usepackage{titletoc} % 控制目录的宏包 34 | \usepackage[perpage,symbol]{footmisc} % 脚注控制 35 | \usepackage{fancyhdr} % fancyhdr宏包 页眉和页脚的相关定义 36 | \usepackage{fancyref} 37 | \usepackage{array} %增强表格的功能 %可能与xeCJK宏包冲突,需放在xeCJK之前。 38 | 39 | \ifx\atempxetex\usewhat 40 | \usepackage[slantfont,boldfont,CJKaddspaces]{xeCJK} % 41 | \CJKlanguage{zh-cn} 42 | \else 43 | \usepackage{CJKutf8} %CJKpunct} % 中文支持宏包 44 | \usepackage{times} % 使用Times字体的宏包 45 | \fi 46 | 47 | \usepackage{type1cm} % tex1cm宏包,控制字体的大小 48 | \usepackage{indentfirst} % 首行缩进宏包 49 | \usepackage{color} % 支持彩色 50 | 51 | \usepackage{amsmath} % AMSLaTeX宏包 用来排出更加漂亮的公式 52 | \usepackage{relsize} % 调整公式字体大小 \mathsmaller \mathlarger 53 | \usepackage{amssymb} 54 | \usepackage{textcomp} % 千分号等特殊符号 55 | \usepackage{mathrsfs} % 不同于\mathcal or \mathfrak 之类的英文花体字体 56 | \usepackage{bm} % 处理数学公式中的黑斜体的宏包 57 | \usepackage[amsmath,thmmarks,hyperref]{ntheorem}% 定理类环境宏包,其中 amsmath 选项用来兼容 AMS LaTeX 的宏包 58 | \usepackage{epsfig} % eps图像 59 | \usepackage[below]{placeins}%允许上一个section的浮动图形出现在下一个section的开始部分,还提供\FloatBarrier命令,使所有未处理的浮动图形立即被处理 60 | %\usepackage{psfrag} %替换eps图形中的文字 61 | %\usepackage{floatflt} % 图文混排用宏包,texlive2008默认不带此宏包,可以自己安装,若是不需要这个功能可以不管它。 62 | \usepackage{wrapfig} 63 | \usepackage{rotating} % 图形和表格的控制 64 | %\usepackage{endfloat} %可将浮动对象放置到文件的最后 65 | \usepackage{setspace} % 定制表格和图形的多行标题行距 66 | \usepackage{flafter} % 使得所有浮动体不能被放置在其浮动环境之前,以免浮动体在引述它的文本之前出现. 67 | \usepackage{multirow} %使用Multirow宏包,使得表格可以合并多个row格 68 | \usepackage{booktabs} % 表格,横的粗线;\specialrule{1pt}{0pt}{0pt} 69 | \usepackage{longtable} %支持跨页的表格。 70 | %\usepackage[centerlast]{caption2} %浮动图形和表格标题样式,这里已被ccaption完全替代。 71 | \usepackage[hang,center]{subfigure}%支持子图 %centerlast 设置最后一行是否居中 72 | \usepackage[subfigure]{ccaption} %,caption2, 73 | 74 | %\usepackage{cite} % 支持引用的宏包 75 | \usepackage[sort&compress,numbers]{natbib}% 支持引用缩写的宏包 76 | \usepackage{hypernat} 77 | 78 | \usepackage{enumitem} %使用enumitem宏包,改变列表项的格式 79 | \usepackage{calc} %长度可以用+ - * / 进行计算 80 | 81 | 82 | % 生成有书签的pdf及其开关, 该宏包应放在所有宏包的最后, 宏包之间有冲突 83 | \def\atemp{dvipspdf}\ifx\atemp\usewhat 84 | \usepackage[dvips,unicode, 85 | bookmarksnumbered=true, 86 | bookmarksopen=true, 87 | colorlinks=false, % 最后打印的时候可以改成false,这样字体都是黑色 88 | pdfborder={0 0 1}, % 去掉链接的边框 89 | citecolor=blue, 90 | linkcolor=red, 91 | anchorcolor=green, 92 | urlcolor=blue, 93 | breaklinks=true 94 | ]{hyperref} 95 | \usepackage{breakurl} %消除dvips的时候网页链接断行失效的问题。 96 | \fi 97 | 98 | \def\atemp{dvipdfmx}\ifx\atemp\usewhat 99 | \usepackage[dvipdfm,unicode, %dvi-->pdf 生成书签 100 | bookmarksnumbered=true, 101 | bookmarksopen=true, 102 | colorlinks=false, 103 | pdfborder={0 0 1}, 104 | citecolor=blue, 105 | linkcolor=red, 106 | anchorcolor=green, 107 | urlcolor=blue, 108 | breaklinks=true 109 | ]{hyperref} 110 | \fi 111 | 112 | \def\atemp{pdflatex}\ifx\atemp\usewhat 113 | \usepackage{cmap} %pdflatex编译时,可以生成可复制、粘贴的中文PDF文档 114 | \usepackage[pdftex,unicode, 115 | %CJKbookmarks=true, 116 | bookmarksnumbered=true, 117 | bookmarksopen=true, 118 | colorlinks=false, 119 | pdfborder={0 0 1}, 120 | citecolor=blue, 121 | linkcolor=red, 122 | anchorcolor=green, 123 | urlcolor=blue, 124 | breaklinks=true 125 | ]{hyperref} 126 | \fi 127 | 128 | \def\atemp{yap}\ifx\atemp\usewhat 129 | \usepackage[dvipdfmx,unicode, %考虑到yap可以正反向搜索,dvipdf使yap中的链接有效。 130 | %CJKbookmarks=true, 131 | bookmarksnumbered=true, 132 | bookmarksopen=true, 133 | colorlinks=false, 134 | pdfborder={0 0 1}, 135 | citecolor=blue, 136 | linkcolor=red, 137 | anchorcolor=green, 138 | urlcolor=blue, 139 | breaklinks=true 140 | ]{hyperref} 141 | \fi 142 | 143 | \ifx\atempxetex\usewhat %\def\atempxetex{xelatex} main.tex中已定义; 144 | \usepackage[xetex, 145 | bookmarksnumbered=true, 146 | bookmarksopen=true, 147 | colorlinks=false, 148 | pdfborder={0 0 0}, 149 | citecolor=blue, 150 | linkcolor=red, 151 | anchorcolor=green, 152 | urlcolor=blue, 153 | breaklinks=true, 154 | naturalnames %与algorithm2e宏包协调 155 | ]{hyperref} 156 | \fi 157 | \usepackage{colortbl, booktabs} 158 | \usepackage{arydshln} %分块矩阵画虚线,挺好用 159 | 160 | \usepackage[boxed,linesnumbered,algochapter]{algorithm2e} % 算法的宏包,注意宏包兼容性,先后顺序为float、hyperref、algorithm(2e),否则无法生成算法列表 161 | \usepackage{listings} 162 | \lstset{basicstyle=\ttfamily, 163 | stringstyle=\ttfamily, 164 | xleftmargin=2em, 165 | xrightmargin=2em, 166 | showstringspaces=false, 167 | breaklines=true, 168 | breakatwhitespace=true, 169 | aboveskip=1em} 170 | \usepackage{latexsym} 171 | \usepackage{fancyvrb} 172 | \usepackage{boxedminipage} 173 | \usepackage{eqlist} 174 | -------------------------------------------------------------------------------- /setup/type.tex: -------------------------------------------------------------------------------- 1 | % -*-coding: utf-8 -*- 2 | 3 | % 硕博类型 的一些定义 4 | 5 | %% 导言区使用中文 6 | \makeatletter 7 | \@tempcnta=128 8 | \loop \catcode\@tempcnta=13 \ifnum\@tempcnta<255 \advance \@tempcnta \@ne 9 | \repeat 10 | \makeatother 11 | 12 | \newif\ifxueweidoctor %判断论文类型 13 | \newif\ifxueweimaster 14 | \def\temp{Doctor} 15 | \ifx\temp\xuewei 16 | \xueweidoctortrue \xueweimasterfalse 17 | \fi 18 | \def\temp{Master} 19 | \ifx\temp\xuewei 20 | \xueweidoctorfalse \xueweimastertrue 21 | \fi 22 | 23 | \ifxueweidoctor 24 | \newcommand{\cxuewei}{博士} 25 | \newcommand{\exuewei}{Doctor} 26 | \newcommand{\exueweier}{Doctoral} 27 | \newcommand{\xueweishort}{博} 28 | \fi 29 | 30 | \ifxueweimaster 31 | \newcommand{\cxuewei}{硕士} 32 | \newcommand{\exuewei}{Master} 33 | \newcommand{\exueweier}{Master} 34 | \newcommand{\xueweishort}{硕} 35 | \fi 36 | 37 | 38 | \ifxueweidoctor 39 | \def\oneortwoside{twoside} 40 | \fi 41 | 42 | \ifx\oneortwoside\undefined 43 | \def\oneortwoside{twoside} 44 | \fi 45 | 46 | \newif\ifoneortwoside 47 | \def\temp{twoside} 48 | \ifx\temp\oneortwoside 49 | \oneortwosidetrue 50 | \else 51 | \oneortwosidefalse 52 | \fi 53 | -------------------------------------------------------------------------------- /xeCJK.chr: -------------------------------------------------------------------------------- 1 | % -*- coding: utf-8 -*- 2 | % This is the file xeCJK.chr of the xeCJK package 3 | % for typesetting Chinese/Japanese/Korean with XeLaTeX 4 | % 5 | % created by Wenchang Sun 6 | % 7 | % Version 2.1.1 (17-July-2008) 8 | % 9 | % Copyright (C) Wenchang Sun 10 | % 11 | % This file may be distributed and/or modified under the 12 | % conditions of the LaTeX Project Public License, either version 1.3 13 | % of this license or (at your option) any later version. 14 | % The latest version of this license is in 15 | % http://www.latex-project.org/lppl.txt 16 | % and version 1.3 or later is part of all distributions of LaTeX 17 | % version 2005/12/01 or later. 18 | % 19 | % 20 | %\edef\xeCJKcatcodeat{\the\catcode`\@}% save catcode of @ 21 | %\edef\xeCJKendlinechar{\the\endlinechar}% save endlinechar 22 | %\catcode`\@=11\relax 23 | %\endlinechar \m@ne 24 | 25 | \def\fileversion{2.1.1} 26 | \def\filedate{2008/07/17} 27 | \ProvidesFile{xeCJK.chr}[\filedate\space\fileversion] 28 | 29 | %\def\xeCJKglue{\hskip 0.1em plus 0.05em minus 0.05em $aa$} 30 | 31 | % Output CJK fonts 32 | % 33 | \DeclareRobustCommand{\xeCJK@char}[1]{ 34 | {\XeTeXinterchartokenstate=0 35 | \CJKsymbol{#1} 36 | \xeCJK@CJKkern} 37 | \xeCJK@ignorespaces} 38 | 39 | % for punctuation. 40 | \DeclareRobustCommand{\xeCJK@prepunctchar}[1]{ 41 | {\xeCJK@punctrule 42 | \ifcsname @xeCJK@preglue#1\endcsname 43 | \ifnum\lastkern>1\relax 44 | \unkern 45 | \unkern 46 | \xeCJK@unskip 47 | \csname @xeCJK@kern\@xeCJK@lastpunct#1\endcsname 48 | \xeCJKpunctnobreak 49 | \else 50 | \xeCJK@ULspecials 51 | \csname @xeCJK@preglue#1\endcsname 52 | \fi 53 | 54 | \global\edef\@xeCJK@lastpunct{#1} 55 | \csname @xeCJK@prerule#1\endcsname 56 | 57 | \XeTeXinterchartokenstate=0 58 | \CJKpunctsymbol{#1} 59 | 60 | \csname @xeCJK@postrule#1\endcsname 61 | \nobreak 62 | \else 63 | \xeCJK@char{#1} 64 | \fi 65 | \gdef\xeCJK@lastcharclass{2} 66 | \xeCJK@prepunctkern} 67 | \ignorespaces} 68 | 69 | \DeclareRobustCommand{\xeCJK@postpunctchar}[1]{ 70 | {\xeCJK@punctrule 71 | \ifcsname @xeCJK@postglue#1\endcsname 72 | \ifnum\lastkern>1\relax 73 | \unkern 74 | \unkern 75 | \xeCJK@unskip 76 | \csname @xeCJK@kern\@xeCJK@lastpunct#1\endcsname 77 | \nobreak 78 | \else 79 | \xeCJK@ULspecials 80 | \ifcsname @xeCJK@punctbreak#1\endcsname 81 | \CJKglue % breakable 82 | \else 83 | \nobreak 84 | \fi 85 | \fi 86 | 87 | \global\edef\@xeCJK@lastpunct{#1} 88 | \csname @xeCJK@prerule#1\endcsname 89 | 90 | \XeTeXinterchartokenstate=0 91 | \CJKpunctsymbol{#1} 92 | 93 | \csname @xeCJK@postrule#1\endcsname 94 | \csname @xeCJK@postglue#1\endcsname 95 | \else 96 | \xeCJK@char{#1} 97 | \fi 98 | \gdef\xeCJK@lastcharclass{3} 99 | \xeCJK@postpunctkern} 100 | \xeCJK@ignorespaces} 101 | 102 | \let\xeCJK@unskip\unskip 103 | \def\xeCJK@UL@unskip{ 104 | \hskip\csname xeCJK@punctglue@\@xeCJK@lastpunct\endcsname\relax} 105 | 106 | \def\xeCJKallowbreakbetweenpuncts{ 107 | \def\xeCJKpunctnobreak{ 108 | \ifnum\xeCJK@lastcharclass=3 109 | \hskip 0pt 110 | \fi}} 111 | 112 | \def\xeCJKnobreakbetweenpuncts{ 113 | \let\xeCJKpunctnobreak\nobreak} 114 | \xeCJKnobreakbetweenpuncts 115 | 116 | \def\@xeCJK@kern#1#2 #3\relax{ 117 | \ifdim #3em=\z@ 118 | \global\expandafter\let\csname @xeCJK@kern#1#2\endcsname\relax 119 | \else 120 | \expandafter\gdef\csname @xeCJK@kern#1#2\endcsname{ 121 | \kern #3em} 122 | \fi} 123 | \let\UTFkern\@xeCJK@kern 124 | 125 | \def\xeCJK@punct#1 #2 #3 #4 #5 #6 #7\relax{ 126 | \ifnum #2=1\relax 127 | \XeTeXcharclass `#1 3\relax 128 | \else 129 | \XeTeXcharclass `#1 2\relax 130 | \fi 131 | % glue and nobreak flag before a punct char 132 | \@xeCJK@before@punct{#1}{}#2 #4\relax 133 | % glue and nobreak flag after a punct char 134 | \@xeCJK@after@punct{#1}{}#5 #7\relax 135 | % zero-height rule added before a punct char 136 | \ifdim #3\p@ = \z@ 137 | \global\expandafter\let\csname 138 | @xeCJK@prerule#1\endcsname=\relax 139 | \else 140 | \global\expandafter\def\csname @xeCJK@prerule#1\endcsname{ 141 | \vrule width #3em depth \z@ height \z@} 142 | \fi 143 | 144 | % zero-height rule added after a punct char 145 | \ifdim #6\p@ = \z@ 146 | \global\expandafter\let\csname 147 | @xeCJK@postrule#1\endcsname=\relax 148 | \else 149 | \global\expandafter\def\csname 150 | @xeCJK@postrule#1\endcsname{ 151 | \vrule width #6em depth \z@ height \z@} 152 | \fi} 153 | \let\UTFpunct\xeCJK@punct 154 | 155 | \def\UTFraisechar#1 #2\relax{ 156 | \expandafter\gdef\csname xeCJK@raise@#1\endcsname{#2 em}} 157 | 158 | \def\@xeCJK@before@punct#1#2#3 #4,#5,#6,#7\relax{ 159 | \ifnum #3#4=\z@ 160 | \global\expandafter\def\csname @xeCJK@preglue#1\endcsname{ 161 | \ifnum\lastkern<2\relax 162 | \nobreak 163 | \fi} 164 | \else 165 | \if #31\relax 166 | \global\expandafter\def\csname @xeCJK@preglue#1\endcsname{ 167 | \nobreak} 168 | \else 169 | \global\expandafter\def\csname @xeCJK@preglue#1\endcsname{ 170 | \ifnum\lastkern<2\relax 171 | \nobreak 172 | \fi 173 | \hskip #5em plus #6em minus #7em\relax} 174 | \fi 175 | \fi} 176 | 177 | \def\@xeCJK@after@punct#1#2#3 #4,#5,#6,#7\relax{ 178 | \ifnum #3#4=\z@ 179 | \global\expandafter\let\csname @xeCJK@postglue#1\endcsname=\relax 180 | \else 181 | \if #41\relax 182 | \global\expandafter\def\csname @xeCJK@postglue#1\endcsname{ 183 | \hskip #5em plus #6em minus #7em} 184 | \else 185 | \global\expandafter\def\csname @xeCJK@postglue#1\endcsname{ 186 | \nobreak} 187 | \fi 188 | \global\expandafter\def\csname xeCJK@punctglue@#1\endcsname{ 189 | -#5em} 190 | \fi} 191 | 192 | \IfFileExists{cjkdefkern.cfg} 193 | {\input{cjkdefkern.cfg}} 194 | {\typeout{Warning: config file cjkdefkern.cfg not found.}} 195 | 196 | \def\xeCJK@Currenttblbase{} 197 | \def\xeCJK@punctrule{ 198 | \xeCJK@gettblbase 199 | \ifx\xeCJK@tblbase\xeCJK@Currenttblbase 200 | \else 201 | \ifcsname xeCJK@\xeCJK@tblbase\endcsname 202 | \else 203 | \IfFileExists{\xeCJK@tblbase.tbl} 204 | {\edef\xeCJK@temp{\xeCJK@tblbase.tbl}} 205 | {\edef\xeCJK@temp{\xeCJK@language\xeCJK@pstyle def.tbl} 206 | \global\expandafter\def\csname xeCJK@\xeCJK@tblbase\endcsname{ 207 | \csname xeCJK@\xeCJK@language\xeCJK@pstyle def\endcsname} 208 | \typeout{Warning: \xeCJK@tblbase.tbl not found, using 209 | \xeCJK@temp\space instead.}} 210 | 211 | \bgroup 212 | \catcode`\\=0 \catcode`\%= 14 \catcode`\^^Z=10 213 | \catcode`\^^I=10 \catcode`\ =10 \catcode`\^^M=5 214 | \catcode`\@=11 215 | \catcode`.=12 \catcode`,=12 \catcode`-=12 \catcode`+=12 216 | \catcode`0=12 \catcode`1=12 \catcode`2=12 \catcode`3=12 217 | \catcode`4=12 \catcode`5=12 \catcode`6=12 \catcode`7=12 218 | \catcode`8=12 \catcode`9=12 219 | \catcode`\{=1 \catcode`\}=2 220 | \@tempcnta="40 221 | \loop 222 | \advance\@tempcnta 1\relax 223 | \catcode\@tempcnta=11\relax 224 | \ifnum\the\@tempcnta<"5A\repeat 225 | 226 | \@tempcnta="60 227 | \loop 228 | \advance\@tempcnta 1\relax 229 | \catcode\@tempcnta=11\relax 230 | \ifnum\the\@tempcnta<"7A\repeat 231 | 232 | \IfFileExists{\xeCJK@temp} 233 | {\input{\xeCJK@temp}} 234 | {\typeout{Warning: File \xeCJK@temp\space not found.}} 235 | \egroup 236 | 237 | \fi 238 | \csname xeCJK@\xeCJK@tblbase\endcsname 239 | \global\let\xeCJK@Currenttblbase\xeCJK@tblbase 240 | \fi} 241 | 242 | \def\xeCJK@gettblbase{ 243 | \ifcsname tblbase\xeCJK@pstyle @\xeCJK@family/\f@series/\f@shape\endcsname 244 | \edef\xeCJK@tblbase{\csname 245 | tblbase\xeCJK@pstyle @\xeCJK@family/\f@series/\f@shape\endcsname} 246 | \else 247 | {\csname xeCJK@font@\xeCJK@family\endcsname 248 | \get@external@font 249 | \global\let\xeCJK@tempx\external@font} 250 | \expandafter\xeCJK@@gettblbase\xeCJK@tempx\relax 251 | \global\expandafter\edef\csname 252 | tblbase\xeCJK@pstyle @\xeCJK@family/\f@series/\f@shape\endcsname{\xeCJK@tblbase} 253 | \fi} 254 | 255 | \def\xeCJK@@gettblbase"#1/#2"#3\relax{ 256 | \edef\xeCJK@temp{\xeCJK@language\xeCJK@pstyle\zap@space #1 \@empty} 257 | \edef\xeCJK@temp{\lowercase{\def\noexpand\xeCJK@tblbase{\xeCJK@temp}}} 258 | \xeCJK@temp 259 | \def\temp{} 260 | \expandafter\xeCJK@stringtoascii\xeCJK@tblbase[] 261 | \edef\xeCJK@tblbase{\temp}} 262 | 263 | \def\xeCJK@stringtoascii#1{ 264 | \ifnum\number`#1>127\relax 265 | \edef\temp{\temp\number`#1} 266 | \else 267 | \edef\temp{\temp\string#1} 268 | \fi 269 | \@ifnextchar[{\xeCJK@gobbletwo}{\xeCJK@stringtoascii}} 270 | 271 | \def\xeCJK@gobbletwo[]{} 272 | 273 | \def\punctstyle#1{ 274 | \ifcsname xeCJK@ps@#1\endcsname 275 | \edef\xeCJK@pstyle{\csname xeCJK@ps@#1\endcsname} 276 | \ifcsname xeCJK@raisechar@\xeCJK@language\xeCJK@pstyle\endcsname 277 | \let\xeCJK@raisechar\xeCJK@@raisechar 278 | \else 279 | \let\xeCJK@raisechar\relax 280 | \fi 281 | \else 282 | \typeout{Warning: Punctstyle #1\space is not defined.} 283 | \fi} 284 | 285 | \def\xeCJK@@raisechar#1{ 286 | \ifcsname xeCJK@raise@#1\endcsname 287 | \raise\csname xeCJK@raise@#1\endcsname\hbox{#1} 288 | \else 289 | #1 290 | \fi} 291 | 292 | \def\xeCJK@raisechar@chtz{} 293 | 294 | \def\xeCJK@ps@kaiming{k} 295 | \def\xeCJK@ps@banjiao{b} 296 | \def\xeCJK@ps@hangmobanjiao{h} 297 | \def\xeCJK@ps@quanjiao{q} 298 | \def\xeCJK@ps@juzhong{z} 299 | \def\xeCJK@ps@CCT{c} 300 | \punctstyle{CCT} 301 | 302 | 303 | 304 | \let\@afterindentfalse\relax 305 | 306 | \def\zhcnparindent{} 307 | 308 | \def\xeCJKplainchr{ 309 | \def\xeCJK@char##1{ 310 | {\XeTeXinterchartokenstate=0 311 | \CJKsymbol{##1} 312 | \xeCJK@CJKkern} 313 | \xeCJK@ignorespaces} 314 | % 315 | % for punctuation. 316 | \def\xeCJK@prepunctchar##1{ 317 | {\ifodd\lastkern 318 | \CJKglue 319 | \else 320 | \ifnum\lastkern=2\relax 321 | \CJK@nobreakglue 322 | \fi 323 | \fi 324 | \XeTeXinterchartokenstate=0 325 | \CJKpunctsymbol{##1} 326 | \xeCJK@prepunctkern} 327 | \ignorespaces} 328 | % 329 | % 330 | \def\xeCJK@postpunctchar##1{ 331 | \CJK@nobreakglue 332 | {\XeTeXinterchartokenstate=0 333 | \CJKpunctsymbol{##1} 334 | \xeCJK@postpunctkern} 335 | \xeCJK@ignorespaces}} 336 | 337 | \def\UTFpunctbreak#1{ 338 | \expandafter\gdef\csname @xeCJK@punctbreak#1\endcsname{}} 339 | 340 | %\endlinechar=\xeCJKendlinechar 341 | 342 | 343 | 344 | \def\xeCJK@gobbleone#1{} 345 | 346 | %\catcode`\@=\xeCJKcatcodeat 347 | 348 | 349 | 350 | -------------------------------------------------------------------------------- /xeCJK.sty: -------------------------------------------------------------------------------- 1 | % -*- coding: utf-8 -*- 2 | % This is the file xeCJK.sty of the xeCJK package 3 | % for typesetting Chinese/Japanese/Korean with XeLaTeX 4 | % 5 | % created by Wenchang Sun 6 | % 7 | % Version 2.1.1 (17-July-2008) 8 | % 9 | % Copyright (C) Wenchang Sun 10 | % 11 | % This file may be distributed and/or modified under the 12 | % conditions of the LaTeX Project Public License, either version 1.3 13 | % of this license or (at your option) any later version. 14 | % The latest version of this license is in 15 | % http://www.latex-project.org/lppl.txt 16 | % and version 1.3 or later is part of all distributions of LaTeX 17 | % version 2005/12/01 or later. 18 | % 19 | % 2008/04/23: \addto@hook\UL@hook{\CJKnospaces} 20 | % 2008/04/19: Change the CJK range: 21 | % 22 | \RequirePackage{ifxetex} 23 | \RequireXeTeX 24 | \def\fileversion{2.1.1} 25 | \def\filedate{2008/07/17} 26 | \ProvidesPackage{xeCJK}[\filedate\space\fileversion] 27 | 28 | \XeTeXdefaultencoding "UTF-8" 29 | \XeTeXinputencoding "UTF-8" 30 | 31 | \RequirePackage{fontspec} 32 | 33 | 34 | \newif\ifxeCJK@SlantFont@ 35 | \xeCJK@SlantFont@false 36 | 37 | \newif\ifxeCJK@BoldFont@ 38 | \xeCJK@BoldFont@false 39 | 40 | \newif\ifxeCJK@num 41 | \xeCJK@numfalse 42 | 43 | \newif\ifxeCJK@addspaces 44 | \xeCJK@addspacesfalse 45 | 46 | \newif\ifxeCJK@nospaces 47 | \xeCJK@nospacesfalse 48 | 49 | \DeclareOption{boldfont}{\xeCJK@BoldFont@true} 50 | \DeclareOption{BoldFont}{\ExecuteOptions{boldfont}} 51 | \DeclareOption{slantfont}{\xeCJK@SlantFont@true} 52 | \DeclareOption{SlantFont}{\ExecuteOptions{slantfont}} 53 | \DeclareOption{CJKnumber}{\xeCJK@numtrue} 54 | \DeclareOption{CJKaddspaces}{\xeCJK@addspacestrue} 55 | \DeclareOption{CJKnormalspaces}{\xeCJK@addspacesfalse} 56 | \DeclareOption{CJKnospaces}{\xeCJK@nospacestrue} 57 | 58 | \ProcessOptions\relax 59 | 60 | \endlinechar \m@ne 61 | 62 | % set XeTeXcharclass for CJK characters: 63 | % 64 | % 1: normal char 65 | % 2: prepunct 66 | % 3: postpunct 67 | \XeTeXinterchartokenstate=1\relax 68 | 69 | \def\xeCJKsetcharclass#1#2#3{ 70 | \@tempcnta=#1 71 | \loop 72 | \XeTeXcharclass \@tempcnta #3\relax 73 | \advance\@tempcnta 1\relax 74 | \ifnum\the\@tempcnta<#2 \repeat} 75 | 76 | % 77 | % For CJK characters 78 | \xeCJKsetcharclass{"3000}{"FFFF}{1} 79 | 80 | \def\xeCJK@prePunct#1#2{\xeCJK@setPunct{2}{#1}{#2}} 81 | \def\xeCJK@postPunct#1#2{\xeCJK@setPunct{3}{#1}{#2}} 82 | 83 | \def\xeCJK@setPunct#1#2#3{ 84 | \def\xeCJK@class{#1} 85 | \@tempcnta "#2\relax 86 | \multiply\@tempcnta 256\relax 87 | \xeCJK@setPunct@#3,,} 88 | 89 | \def\xeCJK@setPunct@#1,{ 90 | \edef\xeCJK@temp{#1}% 91 | \ifx\xeCJK@temp\@empty 92 | \else 93 | \@tempcntb "#1\relax 94 | \advance\@tempcntb\@tempcnta\relax 95 | \XeTeXcharclass \@tempcntb=\xeCJK@class\relax 96 | \def\xeCJK@temp{\xeCJK@setPunct@} 97 | \fi 98 | \xeCJK@temp} 99 | 100 | \xeCJK@prePunct{20}{18,1C} 101 | \xeCJK@postPunct{20}{19,1D,14,26} 102 | \xeCJK@prePunct{30}{08,0A,0C,0E,10,12,14,16,18,1A,1D,1F,36} 103 | 104 | \xeCJK@postPunct{30}{01,02,05,06,09,0B,0D,0F,11,15,17,19,1B,1E, 105 | 41,43,45,47,49,63,83,85,87,8E, 106 | 9B,9C,9D,9E,A1,A3,A5,A7,A9,C3,E3,E5,E7,EE,F5,F6,FB,FC,FD,FE} 107 | \xeCJK@prePunct {FE}{59,5B,5D,5F,60,69,6B} 108 | \xeCJK@postPunct{FE}{50,51,52,54,55,56,57,5A,5C,5E,6A} 109 | \xeCJK@prePunct {FF}{03,04,08,20,3B,5B,E0,E1,E5,E6} 110 | \xeCJK@postPunct{FF}{01,05,09,0C,0E,1A,1B,1F,3D,5D, 111 | 61,63,64,65,67,68,69,6A,6B,6C,6D,6E,6F,70,9E,9F} 112 | 113 | \xeCJK@setPunct{4}{0}{28,5B,60,7B} 114 | \xeCJK@setPunct{5}{0}{21,22,25,27,29,2C,2E,3A,3B,3F,5D,7D} 115 | 116 | % prevent from loading CJK.sty 117 | % and suppress any warning message like 118 | % 119 | % You have requested version 'xxxx/xx/xx' of CJK, 120 | % but only version 'xxxx/xx/xx' is available. 121 | % 122 | \expandafter\def\csname ver@CJK.sty\endcsname{2020/01/01} 123 | 124 | \XeTeXinterchartoks 0 255 {\xeCJK@@cclv} 125 | \XeTeXinterchartoks 0 1 {\xeCJK@@i\xeCJK@char} 126 | \XeTeXinterchartoks 4 1 {\xeCJK@char} 127 | \XeTeXinterchartoks 5 1 {\xeCJK@v@i\xeCJK@char} 128 | \XeTeXinterchartoks 255 1 {\xeCJK@cclv@i\xeCJK@char} 129 | 130 | \XeTeXinterchartoks 0 2 {\xeCJK@prepunctchar} 131 | \XeTeXinterchartoks 4 2 {\xeCJK@prepunctchar} 132 | \XeTeXinterchartoks 5 2 {\xeCJK@prepunctchar} 133 | \XeTeXinterchartoks 255 2 {\xeCJK@prepunctchar} 134 | 135 | \XeTeXinterchartoks 0 3 {\xeCJK@postpunctchar} 136 | \XeTeXinterchartoks 4 3 {\xeCJK@postpunctchar} 137 | \XeTeXinterchartoks 5 3 {\xeCJK@postpunctchar} 138 | \XeTeXinterchartoks 255 3 {\xeCJK@postpunctchar} 139 | 140 | \XeTeXinterchartoks 255 0 {\xeCJK@cclv@} 141 | \XeTeXinterchartoks 255 4 {\xeCJK@cclv@iv} 142 | 143 | \def\CJKglue{\hskip \z@ \@plus .08\baselineskip} 144 | \def\CJK@nobreakglue{\nobreak\CJKglue\nobreak} 145 | 146 | \edef\xeCJK@CJKkern{\kern -1sp\kern 1sp} 147 | \edef\xeCJK@prepunctkern{\kern -2sp\kern 2sp} 148 | \edef\xeCJK@postpunctkern{\kern -3sp\kern 3sp} 149 | \edef\xeCJK@zerokern{\kern -4sp\kern 4sp} 150 | 151 | \newif\if@xeCJK@inmath 152 | \@xeCJK@inmathfalse 153 | 154 | 155 | % common macros for \CJKaddspaces and \CJKnormalspaces 156 | % 157 | % 158 | % 159 | \def\xeCJK@ignorespaces{ 160 | \futurelet\xeCJK@nexttoken\xeCJK@checknext} 161 | 162 | \def\xeCJK@checknext{ 163 | \ifx\xeCJK@nexttoken\@sptoken 164 | \expandafter\xeCJK@@checknext 165 | \fi} 166 | 167 | { 168 | \def\:{\xeCJK@@checknext} 169 | \global\expandafter\def\: {\futurelet\@let@token\xeCJK@@@checknext} 170 | } 171 | 172 | \def\CJK@stop{\CJK@stop} 173 | 174 | \def\xeCJK@@@checknext{ 175 | \expandafter\futurelet 176 | \expandafter\xeCJK@tempb 177 | \expandafter\xeCJK@gobble\meaning\@let@token\CJK@stop 178 | \if t\xeCJK@tempb 179 | \else 180 | \let\xeCJK@nexttoken\relax 181 | \CJKecglue 182 | \fi} 183 | 184 | \long\def\xeCJK@gobble#1\CJK@stop{} 185 | 186 | % macros for CJKaddspaces 187 | % 188 | % Make `\$ active to add blank spaces before CJK characters if necessary 189 | \catcode`\^^B=3\relax 190 | \catcode`\$=13 191 | 192 | \def\CJKaddspaces{ 193 | \def\xeCJK@@cclv{{\xeCJK@zerokern}} 194 | 195 | \def\CJKecglue{\hskip 0.25em plus 0.10em minus 0.10em} 196 | \let\xeCJK@@i\CJKecglue 197 | \let\xeCJK@v@i\CJKecglue 198 | 199 | \def\xeCJK@cclv@{ 200 | \ifodd\lastkern 201 | \CJKecglue 202 | \fi} 203 | \let\xeCJK@cclv@iv\xeCJK@cclv@ 204 | 205 | \def\xeCJK@cclv@i{ 206 | \ifcase\lastkern 207 | \hskip 0pt 208 | \or %1 209 | \CJKglue 210 | \or %2 211 | \xeCJK@ULspecials 212 | \or %3 213 | \xeCJK@ULspecials 214 | \or %4 215 | \CJKecglue 216 | \fi} 217 | 218 | \catcode`\$=13} 219 | 220 | \def${ 221 | \ifx\protect \@typeset@protect 222 | \expandafter\xeCJK@math 223 | \else 224 | ^^B 225 | \fi} 226 | 227 | \def\xeCJK@math{ 228 | \futurelet\xeCJK@temp\xeCJK@@math} 229 | 230 | \def\xeCJK@@math{ 231 | \ifx\xeCJK@temp$ 232 | \def\xeCJK@tempb{\xeCJK@@@dmath} 233 | \else 234 | \def\xeCJK@tempb{\xeCJK@@@math} 235 | \fi 236 | \xeCJK@tempb} 237 | 238 | \def\xeCJK@@@dmath#1{^^B^^B} 239 | 240 | \def\xeCJK@@@math{ 241 | \if@xeCJK@inmath 242 | \def\xeCJK@tempb{ 243 | ^^B 244 | \@xeCJK@inmathfalse 245 | \futurelet\xeCJK@temp\xeCJK@aftermath} 246 | \else 247 | \def\xeCJK@tempb{ 248 | \@xeCJK@inmathtrue 249 | \xeCJK@cclv@ 250 | ^^B} 251 | \fi 252 | \xeCJK@tempb} 253 | 254 | \def\xeCJK@aftermath{ 255 | \ifx\xeCJK@temp\@sptoken 256 | \else 257 | \xeCJK@zerokern 258 | \fi} 259 | 260 | % 261 | % 262 | % macros for CJK normal spaces 263 | \catcode`\$=3 264 | \def\CJKnormalspaces{ 265 | \let\xeCJK@@cclv\relax 266 | \let\xeCJK@@i\relax 267 | \let\xeCJK@v@i\relax 268 | \def\CJKecglue{ } 269 | 270 | \def\xeCJK@cclv@{ 271 | \ifodd\lastkern 272 | \xeCJK@@glue 273 | \fi} 274 | \let\xeCJK@cclv@iv\xeCJK@cclv@ 275 | 276 | \def\xeCJK@cclv@i{ 277 | \ifcase\lastkern 278 | \hskip 0pt 279 | \or %1 280 | \CJKglue 281 | \or %2 282 | \xeCJK@ULspecials 283 | \or %3 284 | \xeCJK@ULspecials 285 | \fi} 286 | 287 | \def\xeCJK@@glue{ 288 | \ifx\xeCJK@nexttoken\@sptoken 289 | { } 290 | \fi 291 | \let\xeCJK@nexttoken\relax} 292 | 293 | \catcode`\$=3\relax} 294 | 295 | % 296 | % 297 | % CJK no spaces 298 | \def\CJKnospaces{ 299 | \catcode`\$=3\relax 300 | \let\xeCJK@@cclv\relax 301 | \let\xeCJK@@i\relax 302 | \let\xeCJK@v@i\relax 303 | \let\xeCJK@cclv@\relax 304 | \def\xeCJK@cclv@i{{% We need extra braces for CJKulem/CJKfntef.sty to work. 305 | \ifcase\lastkern 306 | \hskip 0pt 307 | \or % 1 308 | \CJKglue 309 | \or % 2 310 | \xeCJK@ULspecials 311 | \or % 3 312 | \xeCJK@ULspecials 313 | \fi}} 314 | \let\xeCJK@cclv@iv\relax 315 | \let\xeCJK@ignorespaces\ignorespaces} 316 | 317 | \def\xeCJK@setspacemode{ 318 | \ifxeCJK@nospaces 319 | \CJKnospaces 320 | \else 321 | \ifxeCJK@addspaces 322 | \CJKaddspaces 323 | \else 324 | \CJKnormalspaces 325 | \fi 326 | \fi} 327 | 328 | \CJKnormalspaces 329 | 330 | \AtBeginDocument{ 331 | \xeCJK@setspacemode 332 | \ifcsname UL@hook\endcsname 333 | \addto@hook\UL@hook{\CJKnospaces 334 | \let\xeCJK@unskip\xeCJK@UL@unskip 335 | \let\xeCJK@ULspecials\xeCJK@UL@punctgroup} 336 | \fi} 337 | 338 | 339 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%5 340 | % 341 | % Set CJK fonts separately 342 | % 343 | \def\CJKsymbol#1{{\xeCJK@setfont #1}} 344 | 345 | 346 | %\let\CJKpunctsymbol\CJKsymbol 347 | \def\CJKpunctsymbol#1{{\xeCJK@setfont \xeCJK@raisechar{#1}}} 348 | \let\xeCJK@raisechar\relax 349 | 350 | \def\xeCJK@setfont{ 351 | \ifcsname\xeCJK@family/\f@series/\f@shape/\f@size\endcsname 352 | \csname\xeCJK@family/\f@series/\f@shape/\f@size\endcsname 353 | \else 354 | \csname xeCJK@font@\xeCJK@family\endcsname 355 | \get@external@font 356 | \expandafter\global\expandafter\font 357 | \csname\xeCJK@family/\f@series/\f@shape/\f@size\endcsname=\external@font 358 | \fi} 359 | 360 | % some shorthands for CJK font families; arguments are handled by 361 | % \newfontfamily (from fontspec.sty). 362 | 363 | \def\setCJKmainfont{ 364 | \xeCJK@newfontfamily{xeCJK@font@}} 365 | 366 | \let\setCJKromanfont\setCJKmainfont 367 | 368 | \def\setCJKsansfont{ 369 | \xeCJK@newfontfamily{xeCJK@font@sans}} 370 | 371 | \def\setCJKmonofont{ 372 | \xeCJK@newfontfamily{xeCJK@font@mono}} 373 | 374 | \def\setCJKfamilyfont#1{ 375 | \xeCJK@newfontfamily{xeCJK@font@#1}} 376 | 377 | % 378 | % Redefine \sffamily and \ttfamily to set CJKfamily 379 | \DeclareRobustCommand\sffamily 380 | {\not@math@alphabet\sffamily\mathsf 381 | \fontfamily\sfdefault\CJKfamily{sans}\selectfont} 382 | 383 | \DeclareRobustCommand\ttfamily 384 | {\not@math@alphabet\ttfamily\mathtt 385 | \fontfamily\ttdefault\CJKfamily{mono}\selectfont} 386 | 387 | % \xeCJK@newfontfamily is similar to \newfontfamily 388 | % but introduce fake slant/bold fonts for CJK characters. 389 | \newcommand*\xeCJK@newfontfamily[1]{ 390 | \@ifnextchar[ 391 | {\xeCJK@newfontfamily@{#1}} 392 | {\xeCJK@newfontfamily@{#1}[]}} 393 | 394 | \def\xeCJK@newfontfamily@#1[#2]#3{ 395 | % 396 | % Get user defined options 397 | \def\xeCJK@temp{#2} 398 | \expandafter 399 | \xeCJK@getBoldFont\xeCJK@temp BoldFont={}{}\relax 400 | \expandafter 401 | \xeCJK@getBoldItalicFont\xeCJK@temp BoldItalicFont={}{}\relax 402 | \expandafter 403 | \xeCJK@getItalicFont\xeCJK@temp ItalicFont={}{}\relax 404 | 405 | \expandafter 406 | \xeCJK@getBoldItalicFeatures\xeCJK@temp BoldItalicFeatures={}{}\relax 407 | \expandafter 408 | \xeCJK@getBoldFeatures\xeCJK@temp BoldFeatures={}{}\relax 409 | \expandafter 410 | \xeCJK@getItalicFeatures\xeCJK@temp ItalicFeatures={}{}\relax 411 | 412 | \expandafter 413 | \xeCJK@getRawFeature\xeCJK@BoldFeatures RawFeature={}{}\relax 414 | \edef\xeCJK@Bold@RawFeature{\xeCJK@tempRawFeature} 415 | 416 | \expandafter 417 | \xeCJK@getRawFeature\xeCJK@BoldItalicFeatures RawFeature={}{}\relax 418 | \edef\xeCJK@BoldItalic@RawFeature{\xeCJK@tempRawFeature} 419 | 420 | \expandafter 421 | \xeCJK@getRawFeature\xeCJK@ItalicFeatures RawFeature={}{}\relax 422 | \edef\xeCJK@Italic@RawFeature{\xeCJK@tempRawFeature} 423 | 424 | \edef\xeCJK@Features{} 425 | 426 | \ifxeCJK@BoldFont@ 427 | \ifx\xeCJK@BoldFont\@empty 428 | 429 | \ifx\xeCJK@Bold@RawFeature\@empty 430 | \def\xeCJK@Bold@RawFeature{ 431 | embolden=\xeCJK@emboldenfactor} 432 | \else 433 | \edef\xeCJK@Bold@RawFeature{ 434 | embolden=\xeCJK@emboldenfactor, 435 | \xeCJK@Bold@RawFeature} 436 | \fi 437 | 438 | \ifx\xeCJK@BoldFeatures\@empty 439 | \edef\xeCJK@Features{ 440 | BoldFeatures={ 441 | RawFeature={\xeCJK@Bold@RawFeature}}} 442 | \else 443 | \edef\xeCJK@Features{ 444 | BoldFeatures={ 445 | \xeCJK@BoldFeatures, 446 | RawFeature={\xeCJK@Bold@RawFeature}}} 447 | \fi 448 | 449 | \ifx\xeCJK@BoldItalic@RawFeature\@empty 450 | \def\xeCJK@BoldItalic@RawFeature{ 451 | embolden=\xeCJK@emboldenfactor} 452 | \else 453 | \edef\xeCJK@BoldItalic@RawFeature{ 454 | embolden=\xeCJK@emboldenfactor, 455 | \xeCJK@BoldItalic@RawFeature} 456 | \fi 457 | \fi 458 | \fi 459 | 460 | \ifxeCJK@SlantFont@ 461 | \ifx\xeCJK@ItalicFont\@empty 462 | 463 | \ifx\xeCJK@Italic@RawFeature\@empty 464 | \edef\xeCJK@Italic@RawFeature{ 465 | slant=\xeCJK@slantfactor} 466 | \else 467 | \edef\xeCJK@Italic@RawFeature{ 468 | slant=\xeCJK@slantfactor, 469 | \xeCJK@Italic@RawFeature} 470 | \fi 471 | 472 | \ifx\xeCJK@ItalicFeatures\@empty 473 | \edef\xeCJK@ItalicFeatures{ 474 | RawFeature={\xeCJK@Italic@RawFeature}} 475 | \else 476 | \edef\xeCJK@ItalicFeatures{ 477 | \xeCJK@ItalicFeatures, 478 | RawFeature={\xeCJK@Italic@RawFeature}} 479 | \fi 480 | 481 | \ifx\xeCJK@BoldItalic@RawFeature\@empty 482 | \edef\xeCJK@BoldItalic@RawFeature{ 483 | slant=\xeCJK@slantfactor} 484 | \else 485 | \edef\xeCJK@BoldItalic@RawFeature{ 486 | slant=\xeCJK@slantfactor, 487 | \xeCJK@BoldItalic@RawFeature} 488 | \fi 489 | 490 | \ifx\xeCJK@BoldItalicFeatures\@empty 491 | \edef\xeCJK@BoldItalicFeatures{ 492 | RawFeature={\xeCJK@BoldItalic@RawFeature}} 493 | \else 494 | \edef\xeCJK@BoldItalicFeatures{ 495 | \xeCJK@BoldItalicFeatures, 496 | RawFeature={\xeCJK@BoldItalic@RawFeature}} 497 | \fi 498 | 499 | \ifx\xeCJK@Features\@empty 500 | \edef\xeCJK@Features{ 501 | ItalicFeatures={\xeCJK@ItalicFeatures}, 502 | BoldItalicFeatures={\xeCJK@BoldItalicFeatures}} 503 | \else 504 | \edef\xeCJK@Features{ 505 | \xeCJK@Features, 506 | ItalicFeatures={\xeCJK@ItalicFeatures}, 507 | BoldItalicFeatures={\xeCJK@BoldItalicFeatures}} 508 | \fi 509 | \fi 510 | \fi 511 | 512 | \edef\xeCJK@temp{#2} 513 | \ifx\xeCJK@temp\@empty 514 | \else 515 | \edef\xeCJK@temp{,#2} 516 | \fi 517 | 518 | \ifx\xeCJK@Features\@empty 519 | \else 520 | \edef\xeCJK@Features{,\xeCJK@Features} 521 | \fi 522 | 523 | \edef\xeCJK@Features{ 524 | [BoldFont={#3}, 525 | ItalicFont={#3}, 526 | BoldItalicFont={#3}% The first three parameters can be overridden by 527 | % user defined parameters in #2 528 | \xeCJK@temp\xeCJK@Features]} 529 | 530 | \expandafter 531 | \newfontfamily@i\csname #1\expandafter\endcsname 532 | \xeCJK@Features 533 | {#3}} 534 | 535 | \def\xeCJK@setmacro@getkey#1{ 536 | \expandafter\def\csname xeCJK@get#1\endcsname ##1#1=##2##3\relax{ 537 | \expandafter\edef\csname xeCJK@#1\endcsname{##2} 538 | \edef\xeCJK@temp{##1##3}}} 539 | 540 | \xeCJK@setmacro@getkey{BoldFont} 541 | \xeCJK@setmacro@getkey{ItalicFont} 542 | \xeCJK@setmacro@getkey{BoldItalicFont} 543 | \xeCJK@setmacro@getkey{ItalicFeatures} 544 | \xeCJK@setmacro@getkey{BoldFeatures} 545 | \xeCJK@setmacro@getkey{BoldItalicFeatures} 546 | 547 | \def\xeCJK@getRawFeature#1RawFeature=#2#3\relax{ 548 | \edef\xeCJK@tempRawFeature{#2}} 549 | 550 | \define@key[zf]{preparse}{ItalicFeatures}{ 551 | \edef\zf@it@feat{,#1} 552 | \edef\zf@family@long{\zf@family@long itfeat:#1}} 553 | 554 | % redefine \CJKfamily. 555 | 556 | \def\xeCJK@font@{} 557 | 558 | \DeclareRobustCommand\CJKfamily[1]{ 559 | \ifcsname xeCJK@font@#1\endcsname 560 | \def\xeCJK@family{#1} 561 | \else 562 | \ifcsname xeCJK@#1@warned\endcsname 563 | \else 564 | \PackageWarning{xeCJK}{ 565 | Unknown CJK family `#1' is ignored.^^J 566 | Use \string\setCJKfamilyfont \space to define a CJK family.} 567 | \expandafter\gdef\csname xeCJK@#1@warned\endcsname{} 568 | \fi 569 | \fi} 570 | \CJKfamily{} 571 | 572 | \def\xeCJKsetslantfactor#1{\edef\xeCJK@slantfactor{#1}} 573 | \def\xeCJKsetemboldenfactor#1{\edef\xeCJK@emboldenfactor{#1}} 574 | 575 | \xeCJKsetslantfactor{0.17} 576 | \xeCJKsetemboldenfactor{4} 577 | 578 | 579 | % 580 | % Loading language dependent macros. 581 | % 582 | \def\CJKlanguage#1{ 583 | \ifcsname CJK@#1\endcsname 584 | \edef\xeCJK@language{\csname CJK@#1\endcsname} 585 | \else 586 | \PackageWarning{xeCJK}{ 587 | Unknown CJK language `#1' is ignored.^^J 588 | Valid languages are `Chinese-Simp', `Chinese-Trad', `Japanese' and 'Korean'.} 589 | \relax 590 | \fi} 591 | 592 | \expandafter\def\csname CJK@zh-cn\endcsname{chs} 593 | \expandafter\def\csname CJK@Chinese-Simp\endcsname{chs} 594 | \expandafter\def\csname CJK@Chinese-Trad\endcsname{cht} 595 | \expandafter\def\csname CJK@Japanese\endcsname{ja} 596 | \expandafter\def\csname CJK@Korean\endcsname{ko} 597 | \CJKlanguage{Chinese-Simp} 598 | 599 | \input{xeCJK.chr} 600 | 601 | 602 | % macros for using CJKfntef.sty and CJKnumb.sty 603 | % 604 | \@ifundefined{UL@hskip}{\let\UL@hskip\relax}{} 605 | 606 | \let\xeCJK@ULspecials\relax 607 | 608 | \def\xeCJK@UL@punctgroup{ 609 | \ifx\hskip\UL@hskip 610 | \egroup 611 | \UL@stop 612 | \UL@start 613 | \bgroup 614 | \fi} 615 | 616 | 617 | \ifxeCJK@num 618 | \edef\CJK@UnicodeEnc{UTF8} 619 | \def\CJKaddEncHook#1#2{\expandafter\def\csname xeCJK@enc@#1\endcsname{#2}} 620 | \def\Unicode#1#2{\@tempcnta #1\relax 621 | \multiply\@tempcnta 256\relax 622 | \advance\@tempcnta #2\relax 623 | \char\@tempcnta} 624 | \RequirePackage{CJKnumb} 625 | \csname xeCJK@enc@UTF8\endcsname 626 | \def\CJK@tenthousand{涓噠 627 | \fi 628 | 629 | \endlinechar `\^^M 630 | \endinput 631 | --------------------------------------------------------------------------------