gdb init配置文件的使用(1)

更多常用gdbinit配置请参考 https://github.com/gdbinit/Gdbinit/blob/master/gdbinit

当 GDB(即 GNU Project Debugger)启动时,它在当前用户的主目录中寻找一个名为 .gdbinit 的文件;如果该文件存在,则 GDB 就执行该文件中的所有命令。通常,该文件用于简单的配置命令,如设置所需的缺省汇编程序格式(Intel® 或 Motorola)或用于显示输入和输出数据的缺省基数(十进制或十六进制)。它还可以读取宏编码语言,从而允许实现更强大的自定义。该语言遵循如下基本格式:

define <command>

<code>

end

document <command>

<help text>

end

该命令称为用户命令。可以将所有其他标准 GDB 命令与流控制指令结合使用并向其传递参数,从而创建一种语言,以允许为正在调试的特定应用程序而自定义调试器的行为。

从简单开始:清屏

从简单开始并在此基础上逐步发展始终是个好主意。启动 xterm,调出您最喜欢的编辑器,让我们开始创建一个有用的 .gdbinit 文件吧!调试器产生的输出可能非常零乱,根据个人偏好,在使用任何可能产生混乱的工具时,许多人都希望能够清屏。GDB 没有用于清屏的内置命令,但它可以调用 shell 函数;下面的代码跳到调试器之外以使用 cls 命令来清除 xterm 控制台:

define cls

shell clear

end

document cls

Clears the screen with a simple command.

end

此定义的上半部分(在 define ... end 动词所界定的范围内)构成了在调用该命令时所执行的代码。

此定义的下半部分(在 document ... end 所界定的范围内)由 GDB 命令解释器使用,用于在您键入 help cls 时显示与 cls 命令关联的文本。

在将该代码键入 .gdbinit 文件以后,调出 GDB 并输入 cls 命令。此时屏幕被清除,您所看到的就只有 GDB 提示符。您的 GDB 自定义之旅已经开始了!

文档的重要性

如果输入 help user 命令,您会看到已在 .gdbinit 文件中输入的所有用户命令的摘要。.gdbinit 用户定义命令的设计者提供了一个重要特性,您在编写自己的命令时不应忽略该特性:document ... end 子句。随着这些命令数量的增加,维护有关命令如何工作的功能文档将变得非常关键。

您可能已经遇到过此问题。假设您在若干年前编写了一些代码;后来当您重新处理它(也许是为了修正错误或通过添加新特性来修改它)时,您发现自己很难理解您自己的代码。优秀的程序员习惯将代码保持得简短、简单和具有良好的文档记录,以便使其可维护。

适用于编程代码的一般规则也适用于调试器代码。当您在这个最有价值的职业中披荆斩棘地拼搏时,保留仔细的注释和有良好文档记录的代码将为您带来丰厚的回报。

GDB 的社区使用

人类通过多种方式学习新知识,包括研究其他人已做的工作。初学的汽车工程师首先打开他们第一辆车的发动机罩,拔出他们的工具,开始拆卸部件以进行清理和研究。此类活动使他们能够在保持汽车清洁的同时,还了解了汽车引擎是如何工作的。

初学的计算机科学家也没有什么不同,因为他们想了解程序究竟是如何工作的——它们如何与动态库和本机操作系统交互。用于查看这些程序如何工作的工具就是调试器。计算机编程是一项复杂的活动,通过与志趣相投的人群社区交流、提问并获得答案,新的计算机科学家能够满足他们对知识的需要。

在全球编程社区中,始终存在大量渴求知识的人。他们不再满足于在计算机上运行程序——他们还想知道得更多。他们想知道这些程序是如何运行的,并乐此不疲地使用最适当的可用工具来探索系统的功能:调试器。通过逆向工程(一种在调试器下运行程序并密切注意它们如何完成所做的工作,从而了解程序工作原理的方法),您可以从所研究程序的创作者已完成的工作中学到大量的知识。编程中涉及的大量底层详细信息没有相关的文档记录;了解它们的唯一方法就是在它们的实际工作中观察它们。

逆向工程背上了不应有的坏名声,仿佛那只是黑客和犯罪分子企图破坏副本保护系统和编写蠕虫及病毒来对计算机世界造成损害才会干的事情。虽然存在这样的人,但绝大多数使用调试器和逆向工程来研究程序如何工作的人都是当前和将来的软件工程师,他们希望并需要知道这些程序是如何工作的。他们已形成了在线社区以共享他们的知识和发现;抵制该活动是非建设性的,会阻碍计算机科学的未来发展。

本文中定义的许多用户函数就来自于此类知识渴求者的社区。如果希望了解有关他们的更多信息,建议您研究本文的参考资料部分所提到的网站。

断点别名

许多 GDB 命令太繁琐,这是众所周知的事实。尽管可以对它们进行缩写,但是 GDB 宏语言允许实现进一步的简化。诸如 info breakpoints 这样的命令可以变得像 bpl 一样简单。清单 1 显示了一组此类简单和高度有用的断点别名 用户命令,您可以将它们添加到不断增长的 .gdbinit 文件中。

清单 1:断点别名命令

define bpl

info breakpoints

end

document bpl

List breakpoints

end



define bp

set $SHOW_CONTEXT = 1

break * $arg0

end

document bp

Set a breakpoint on address

Usage: bp addr

end



define bpc

clear $arg0

end

document bpc

Clear breakpoint at function/address

Usage: bpc addr

end



define bpe

enable $arg0

end

document bpe

Enable breakpoint #

Usage: bpe num

end



define bpd

disable $arg0

end

document bpd

Disable breakpoint #

Usage: bpd num

end



define bpt

set $SHOW_CONTEXT = 1

tbreak $arg0

end

document bpt

Set a temporary breakpoint on address

Usage: bpt addr

end



define bpm

set $SHOW_CONTEXT = 1

awatch $arg0

end

document bpm

Set a read/write breakpoint on address

Usage: bpm addr

end


 

显示进程信息一旦您习惯了使用断点别名命令,调试会话就变得更有价值了;这些命令极大地提高了调试器的效率,因为它能使您事半功倍。

用户定义的 GDB 命令可由其他用户定义的命令调用,从而为各方都带来更高的效率。这就是编程语言的递增性质——编写底层函数,逐渐由更高层的函数调用,直到您只需最少的工作即可让那些工具方便地完成您想要它们完成的任务。要整合到 .gdbinit 文件中的下一组 GDB 定义将在进程被调用时显示有用的进程信息,如清单 2 所示。

清单 2: 进程信息命令

define argv

show args

end

document argv

Print program arguments

end



define stack

info stack

end

document stack

Print call stack

end



define frame

info frame

info args

info locals

end

document frame

Print stack frame

end



define flags

if (($eflags >> 0xB) & 1 )

printf "O "

else

printf "o "

end

if (($eflags >> 0xA) & 1 )

printf "D "

else

printf "d "

end

if (($eflags >> 9) & 1 )

printf "I "

else

printf "i "

end

if (($eflags >> 8) & 1 )

printf "T "

else

printf "t "

end

if (($eflags >> 7) & 1 )

printf "S "

else

printf "s "

end

if (($eflags >> 6) & 1 )

printf "Z "

else

printf "z "

end

if (($eflags >> 4) & 1 )

printf "A "

else

printf "a "

end

if (($eflags >> 2) & 1 )

printf "P "

else

printf "p "

end

if ($eflags & 1)

printf "C "

else

printf "c "

end

printf "\n"

end

document flags

Print flags register

end



define eflags

printf "     OF <%d>  DF <%d>  IF <%d>  TF <%d>",\

        (($eflags >> 0xB) & 1 ), (($eflags >> 0xA) & 1 ), \

        (($eflags >> 9) & 1 ), (($eflags >> 8) & 1 )

printf "  SF <%d>  ZF <%d>  AF <%d>  PF <%d>  CF <%d>\n",\

        (($eflags >> 7) & 1 ), (($eflags >> 6) & 1 ),\

        (($eflags >> 4) & 1 ), (($eflags >> 2) & 1 ), ($eflags & 1)

printf "     ID <%d>  VIP <%d> VIF <%d> AC <%d>",\

        (($eflags >> 0x15) & 1 ), (($eflags >> 0x14) & 1 ), \

        (($eflags >> 0x13) & 1 ), (($eflags >> 0x12) & 1 )

printf "  VM <%d>  RF <%d>  NT <%d>  IOPL <%d>\n",\

        (($eflags >> 0x11) & 1 ), (($eflags >> 0x10) & 1 ),\

        (($eflags >> 0xE) & 1 ), (($eflags >> 0xC) & 3 )

end

document eflags

Print entire eflags register

end



define reg

printf "     eax:%08X ebx:%08X  ecx:%08X ",  $eax, $ebx, $ecx

printf " edx:%08X     eflags:%08X\n",  $edx, $eflags

printf "     esi:%08X edi:%08X  esp:%08X ",  $esi, $edi, $esp

printf " ebp:%08X     eip:%08X\n", $ebp, $eip

printf "     cs:%04X  ds:%04X  es:%04X", $cs, $ds, $es

printf "  fs:%04X  gs:%04X  ss:%04X    ", $fs, $gs, $ss

flags

end

document reg

Print CPU registers

end



define func

info functions

end

document func

Print functions in target

end



define var

info variables

end

document var

Print variables (symbols) in target

end



define lib

info sharedlibrary

end

document lib

Print shared libraries linked to target

end



define sig

info signals

end

document sig

Print signal actions for target

end



define thread

info threads

end

document thread

Print threads in target

end



define u

info udot

end

document u

Print kernel 'user' struct for target

end



define dis

disassemble $arg0

end

document dis

Disassemble address

Usage: dis addr

end


 

要整合进 .gdbinit 文件中的下一组定义包括增强的十六进制和 ASCII 转储函数,如清单 3 所示。程序员注意:若想创建卓越的软件,则应添加宏编程功能,从而允许用户社区能够增强您的工具以适应他们自己的偏好。GDB 就是一个卓越的软件!十六进制和 ASCII 转储命令

清单 3: 十六进制和 ASCII 转储命令

define ascii_char

set $_c=*(unsigned char *)($arg0)

if ( $_c < 0x20 || $_c > 0x7E )

printf "."

else

printf "%c", $_c

end

end

document ascii_char

Print the ASCII value of arg0 or '.' if value is unprintable

end



define hex_quad

printf "%02X %02X %02X %02X  %02X %02X %02X %02X",                          \

               *(unsigned char*)($arg0), *(unsigned char*)($arg0 + 1),      \

               *(unsigned char*)($arg0 + 2), *(unsigned char*)($arg0 + 3),  \

               *(unsigned char*)($arg0 + 4), *(unsigned char*)($arg0 + 5),  \

               *(unsigned char*)($arg0 + 6), *(unsigned char*)($arg0 + 7)

end

document hex_quad

Print eight hexadecimal bytes starting at arg0

end



define hexdump

printf "%08X : ", $arg0

hex_quad $arg0

printf " - "

hex_quad ($arg0+8)

printf " "



ascii_char ($arg0)

ascii_char ($arg0+1)

ascii_char ($arg0+2)

ascii_char ($arg0+3)

ascii_char ($arg0+4)

ascii_char ($arg0+5)

ascii_char ($arg0+6)

ascii_char ($arg0+7)

ascii_char ($arg0+8)

ascii_char ($arg0+9)

ascii_char ($arg0+0xA)

ascii_char ($arg0+0xB)

ascii_char ($arg0+0xC)

ascii_char ($arg0+0xD)

ascii_char ($arg0+0xE)

ascii_char ($arg0+0xF)



printf "\n"

end

document hexdump

Display a 16-byte hex/ASCII dump of arg0

end



define ddump

printf "[%04X:%08X]------------------------", $ds, $data_addr

printf "---------------------------------[ data]\n"

set $_count=0

while ( $_count < $arg0 )

set $_i=($_count*0x10)

hexdump ($data_addr+$_i)

set $_count++

end

end

document ddump

Display $arg0 lines of hexdump for address $data_addr

end



define dd

if ( ($arg0 & 0x40000000) || ($arg0 & 0x08000000) || ($arg0 & 0xBF000000) )

set $data_addr=$arg0

ddump 0x10

else

printf "Invalid address: %08X\n", $arg0

end

end

document dd

Display 16 lines of a hex dump for $arg0

end



define datawin

if ( ($esi & 0x40000000) || ($esi & 0x08000000) || ($esi & 0xBF000000) )

set $data_addr=$esi

else

if ( ($edi & 0x40000000) || ($edi & 0x08000000) || ($edi & 0xBF000000) )

set $data_addr=$edi

else

if ( ($eax & 0x40000000) || ($eax & 0x08000000) || \

      ($eax & 0xBF000000) )

set $data_addr=$eax

else

set $data_addr=$esp

end

end

end

 ddump 2

end

document datawin

Display esi, edi, eax, or esp in the data window

end


最后,当您调试正在运行的进程时,获得进程上下文的总体视图通常是必要的。清单 4 中有用的进程上下文命令是使用前面定义的数据转储函数来构建的。流程上下文命令

清单 4: 进程上下文命令

define context

printf "_______________________________________"

printf "________________________________________\n"

reg

printf "[%04X:%08X]------------------------", $ss, $esp

printf "---------------------------------[stack]\n"

hexdump $sp+0x30

hexdump $sp+0x20

hexdump $sp+0x10

hexdump $sp

datawin

printf "[%04X:%08X]------------------------", $cs, $eip

printf "---------------------------------[ code]\n"

x /6i $pc

printf "---------------------------------------"

printf "---------------------------------------\n"

end

document context

Print regs, stack, ds:esi, and disassemble cs:eip

end



define context-on

set $SHOW_CONTEXT = 1

end

document context-on

Enable display of context on every program stop

end



define context-off

set $SHOW_CONTEXT = 1

end

document context-on

Disable display of context on every program stop

end



# Calls "context" at every breakpoint.

define hook-stop

  context

end



# Init parameters

set output-radix 0x10

set input-radix 0x10

set disassembly-flavor intel


具有新功能的调试会话hook-stop 是 GDB 在每次发生断点事件时调用的特殊定义。此例中生成了 context 清单,以便您能清楚看到处理器执行每条指令的结果。

让我们试验一下这组新工具,以了解它们在调试我们的“老朋友”(由 IBM developerWorks 供稿作家 Nigel Griffiths 编写的 nweb 服务器代码)时的工作情况。(请参见参考资料部分以获得指向 Nigel 的文章“nweb: a tiny, safe Web server (static pages only)”的链接。)

在将 es-nweb.zip 文件下载到 $HOME/downloads 目录后,键入如下命令以提取、编译和运行 nweb。(请注意,这里假设您是将该程序编译到中央处理单元 (CPU) 为 Intel Pentium 的 Linux® 工作站——该 .gdbinit 代码是仅为 Intel Pentium 类型的处理器和兼容处理器而编写的。)

$ cd src

$ mkdir nweb

$ cd nweb

$ unzip $HOME/downloads/es-nweb.zip

$ gcc -ggdb -O -DLINUX nweb.c -o nweb

$ ./nweb 9090 $HOME/src/nweb &


接下来,为验证 nweb 服务器正在运行,可使用 ps 命令来对它进行检查。注意:此示例中的 -ggdb 选项与 Nigel 文章中所述的选项不同,因为它告诉 GNU 编译器集 (GCC) 优化该程序,以便于使用 GDB 来进行调试。

1

2

3

4

5

$ ps

  PID TTY          TIME CMD

 2913 pts/5    00:00:00 bash

 4009 pts/5    00:00:00 nweb

 4011 pts/5    00:00:00 ps

最后,在您的计算机上启动 Web 浏览器,并在地址栏键入:http://localhost:9090。

下一步是启动 GDB,并与以前一样附加到当前运行的 nweb 实例,如 清单 5 所示。

清单 5:运行 GDB

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

$ gdb --quiet

(gdb) attach 4009

Attaching to process 4009

Reading symbols from /home/bill/src/nweb/nweb...done.

Reading symbols from /lib/tls/libc.so.6...done.

Loaded symbols for /lib/tls/libc.so.6

Reading symbols from /lib/ld-linux.so.2...done.

Loaded symbols for /lib/ld-linux.so.2

_______________________________________________________________________________

     eax:FFFFFE00 ebx:00000005  ecx:BFFFF680  edx:00000001     eflags:00000246

     esi:00000005 edi:00000000  esp:BFFFF66C  ebp:BFFFF6A8     eip:FFFFE410

     cs:0073  ds:007B  es:007B  fs:0000  gs:0033  ss:007B    o d I t s Z a P c

[007B:BFFFF66C]---------------------------------------------------------[stack]

BFFFF69C : 14 0A 13 42  60 53 01 40 - 24 8F 04 08  C8 F6 FF BF ...B`S.@$.......

BFFFF68C : A6 8E 04 08  14 0A 13 42 - 70 C6 00 40  10 00 00 00 .......Bp..@....

BFFFF67C : 82 8E 04 08  00 00 00 00 - C4 C6 04 08  98 F6 FF BF ................

BFFFF66C : A8 F6 FF BF  01 00 00 00 - 80 F6 FF BF  81 EA 0D 42 ...............B

[007B:FFFFFE00]---------------------------------------------------------[ data]

FFFFFE00 : Error while running hook_stop:

Cannot access memory at address 0xfffffe00

0xffffe410 in ?? ()

(gdb)

-quiet 选项告诉 GDB 调试器仅显示其提示符,而不要显示所有其他通常显示的启动信息。如果需要显示额外的文本信息,可以去掉 -quiet 选项。

attach 4009 命令开始对当前正在运行的 nweb 服务器的调试,并且 GDB 调试器通过读取有关该进程的所有符号信息来做出同样方式的响应。

您将会注意到 context 代码运行并显示大量有关当前进程的有用信息,但它不能访问数据段中的内存。这不是个严重问题,并且应该忽略它。有时,保护模式处理器的保护方案不允许您看到您可能希望看到的所有内容。在此情况下,该问题并不重要。

下一步,使用 info 命令来列出有关您所研究的程序的信息(请参见清单 6)。

清单 6:info 命令列出程序信息

1

2

3

4

5

6

(gdb) info proc

process 4009

cmdline = './nweb'

cwd = '/home/bill/src/nweb'

exe = '/home/bill/src/nweb/nweb'

(gdb)

在其运行过程中进行观察

由于您所观察的是一个实际运行的程序,所以可以设置相应的断点,然后在它响应浏览器请求并向发出请求的浏览器传输 .html 和 .jpg 文件时,对该程序进行观察清单 7 表明了如何完成该任务。

清单 7:设置断点

1

2

3

4

5

6

7

8

9

(gdb) b 188

Breakpoint 1 at 0x8048e70: file nweb.c, line 188.

(gdb) commands 1

Type commands for when breakpoint 1 is hit, one per line.

End with a line saying just "end".

>continue

>end

(gdb) c

Continuing.

此时,GDB 调试工具已设置为在 nweb 服务器接受 浏览器请求时所在的行中断,调试器将简单地显示请求并继续处理其他请求,而不会中断正在运行的程序。刷新几次浏览器中的 http://localhost:9090/ 页面,可以观察到,GDB 调试器显示了断点并继续运行。

在刷新浏览器页面的同时,您应该看到如清单 8 所示的断点信息,在 GDB 调试器 xterm 中滚动输出。还可以通过按 Ctrl+C 来停止在 nweb 服务器中的调试。停止跟踪以后,可以通过键入 quit 命令来退出 GDB 调试器。

清单 8: GDB 调试器 xterm 中的断点信息

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

_______________________________________________________________________________

     eax:00000000 ebx:00000001  ecx:00000000  edx:00000001     eflags:00000206

     esi:00000006 edi:00000000  esp:BFFFF690  ebp:BFFFF6A8     eip:08048E70

     cs:0073  ds:007B  es:007B  fs:0000  gs:0033  ss:007B    o d I t s z a P c

[007B:BFFFF690]---------------------------------------------------------[stack]

BFFFF6C0 : 03 00 00 00  D4 86 04 08 - 00 00 00 00  F5 86 04 08 ................

BFFFF6B0 : 03 00 00 00  F4 F6 FF BF - 04 F7 FF BF  2C 58 01 40 ............,X.@

BFFFF6A0 : 60 53 01 40  24 8F 04 08 - C8 F6 FF BF  04 55 01 42 `S.@$........U.B

BFFFF690 : 14 0A 13 42  70 C6 00 40 - 10 00 00 00  14 0A 13 42 ...Bp..@.......B

[007B:BFFFF690]---------------------------------------------------------[ data]

BFFFF690 : 14 0A 13 42  70 C6 00 40 - 10 00 00 00  14 0A 13 42 ...Bp..@.......B

BFFFF6A0 : 60 53 01 40  24 8F 04 08 - C8 F6 FF BF  04 55 01 42 `S.@$........U.B

[0073:08048E70]---------------------------------------------------------[ code]

0x8048e70 <main+718>:   sub    esp,0x4

0x8048e73 <main+721>:   lea    eax,[ebp-16]

0x8048e76 <main+724>:   push   eax

0x8048e77 <main+725>:   push   0x804c6c4

0x8048e7c <main+730>:   push   edi

0x8048e7d <main+731>:   call   0x80485e4 <accept>

------------------------------------------------------------------------------

Breakpoint 1, main (argc=3, argv=0x1) at nweb.c:188

188           if((socketfd = accept(listenfd, (struct sockaddr *)&cli_addr, &length)) < 0)

Program received signal SIGINT, Interrupt.

0xffffe410 in ?? ()

(gdb) quit

The program is running.  Quit anyway (and detach it)? (y or n) y

Detaching from program: /home/bill/src/nweb/nweb, process 4009

$

可以看到,context 函数所显示的信息远比您通常使用缺省 GDB hook_stop 函数所看到的信息更详细。(您还会注意到,现在也可以访问数据段了。)使用这些 GDB 增强,您可以看到每次到达断点和执行每步操作时的确切 CPU 状态。单步执行每个命令并观察寄存器和内存值如何受影响,这也是学习 Intel 机器语言命令基础知识的理想方法。

与所有程序一样,.gdbinit 文件中的代码提供了无穷无尽的增强和改进机会。无论如何,这都不是结束!强烈建议您使用这里描述的命令,并为不断增长的 .gdbinit 自定义集添加更多命令。在您研究和使用这些工具时,请与更广泛的社区分享它们,以使每个人都能增长知识。

  • 4
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
目 录 第1篇 Linux网络开发基础 第1章 Linux操作系统概述 2 1.1 Linux发展历史 2 1.1.1 Linux的诞生和发展 2 1.1.2 Linux名称的由来 1.2 Linux的发展要素 3 1.2.1 UNIX操作系统 4 1.2.2 Minix操作系统 4 1.2.3 POSIX 标准 4 1.3 Linux与UNIX的异同 5 1.4 操作系统类型选择和内核版本的选择 5 1.4.1 常见的不同公司发行的Linux异同 6 1.4.2 内核版本的选择 6 1.5 Linux的系统架构 7 1.5.1 Linux内核的主要模块 7 1.5.2 Linux的文件结构 9 1.6 GNU通用公共许可证 10 1.6.1 GPL许可证的历史 10 1.6.2 GPL的自由理念 10 1.6.3 GPL的基本条款 11 1.6.4 关于GPL许可证的争议 12 1.7 Linux软件开发的可借鉴之处 12 1.8 小结 13 第2章 Linux编程环境 14 2.1 Linux环境下的编辑器 14 2.1.1 vim使用简介 14 2.1.2 使用vim建立文件 15 2.1.3 使用vim编辑文本 16 2.1.4 vim的格式设置 18 2.1.5 vim配置文件.vimrc 19 2.1.6 使用其他编辑器 19 2.2 Linux下的GCC编译器工具集 19 2.2.1 GCC简介 19 2.2.2 编译程序的基本知识 21 2.2.3 单个文件编译成执行文件 22 2.2.4 编译生成目标文件 22 2.2.5 多文件编译 23 2.2.6 预处理 24 2.2.7 编译成汇编语言 24 2.2.8 生成和使用静态链接库 25 2.2.9 生成动态链接库 26 2.2.10 动态加载库 29 2.2.11 GCC常用选项 31 2.2.12 编译环境的搭建 33 2.3 Makefile文件简介 34 2.3.1 一个多文件的工程例子 34 2.3.2 多文件工程的编译 36 2.3.3 Makefile的规则 37 2.3.4 Makefile中使用变量 39 2.3.5 搜索路径 43 2.3.6 自动推导规则 44 2.3.7 递归make 44 2.3.8 Makefile中的函数 46 2.4 用GDB调试程序 47 2.4.1 编译可调试程序 48 2.4.2 使用GDB调试程序 49 2.4.3 GDB常用命令 52 2.4.4 其他的GDB 59 2.5 小结 60 第3章 文件系统简介 61 3.1 Linux下的文件系统 61 3.1.1 Linux下文件的内涵 61 3.1.2 文件系统的创建 62 3.1.3 挂接文件系统 64 3.1.4 索引节点inode 65 3.1.5 普通文件 66 3.1.6 设备文件 66 3.1.7 虚拟文件系统VFS 68 3.2 文件的通用操作方法 72 3.2.1 文件描述符 72 3.2.2 打开创建文件open()、create()函数 72 3.2.3 关闭文件close()函数 76 3.2.4 读取文件read()函数 77 3.2.5 写文件write()函数 79 3.2.6 文件偏移lseek()函数 80 3.2.7 获得文件状态fstat()函数 83 3.2.8 文件空间映射mmap()函数 85 3.2.9 文件属性fcntl()函数 88 3.2.10 文件输入输出控制ioctl()函数 92 3.3 socket文件类型 93 3.4 小结 93 第4章 程序、进程和线程 94 4.1 程序、进程和线程的概念 94 4.1.1 程序和进程的差别 94 4.1.2 Linux环境下的进程 95 4.1.3 进程和线程 96 4.2 进程产生的方式 96 4.2.1 进程号 96 4.2.2 进程复制fork() 97 4.2.3 system()方式 98 4.2.4 进程执行exec()函数系列 99 4.2.5 所有用户态进程的产生进程init 100 4.3 进程间通信和同步 101 4.3.1 半双工管道 101 4.3.2 命名管道 107 4.3.3 消息队列 108 4.3.4 消息队列的一个例子 114 4.3.5 信号量 116 4.3.6 共享内存 121 4.3.7 信号 124 4.4 Linux下的线程 127 4.4.1 多线程编程实例 127 4.4.2 Linux下线程创建函数pthread_create() 129 4.4.3 线程的结束函数pthread_join()和pthread_exit() 129 4.4.4 线程的属性 130 4.4.5 线程间的互斥 132 4.4.6 线程中使用信号量 133 4.5 小结 136 第2篇 Linux用户层网络编程 第5章 TCP/IP协议族简介 138 5.1 OSI网络分层介绍 138 5.1.1 OSI网络分层结构 138 5.1.2 OSI的7层网络结构 139 5.1.3 OSI参考模型中的数据传输 140 5.2 TCP/IP协议栈 141 5.2.1 TCP/IP协议栈参考模型 141 5.2.2 主机到网络层协议 143 5.2.3 IP协议 144 5.2.4 网际控制报文协议(ICMP) 146 5.2.5 传输控制协议(TCP) 150 5.2.6 用户数据报文协议(UDP) 154 5.2.7 地址解析协议(ARP) 156 5.3 IP地址分类与TCP/UDP端口 158 5.3.1 因特网中IP地址的分类 159 5.3.2 子网掩码(subnet mask address) 161 5.3.3 IP地址的配置 162 5.3.4 端口 163 5.4 主机字节序和网络字节序 163 5.4.1 字节序的含义 164 5.4.2 网络字节序的转换 164 5.5 小结 166 第6章 应用层网络服务程序简介 167 6.1 HTTP协议和服务 167 6.1.1 HTTP协议概述 167 6.1.2 HTTP协议的基本过程 168 6.2 FTP协议和服务 170 6.2.1 FTP协议概述 170 6.2.2 FTP协议的工作模式 172 6.2.3 FTP协议的传输方式 172 6.2.4 一个简单的FTP过程 173 6.2.5 常用的FTP工具 173 6.3 TELNET协议和服务 174 6.3.1 远程登录的基本概念 174 6.3.2 使用TELNET协议进行远程登录的工作过程 174 6.3.3 TELNET协议 174 6.4 NFS协议和服务 176 6.4.1 安装NFS服务器和客户端 176 6.4.2 服务器端的设定 176 6.4.3 客户端的操作 177 6.4.4 showmount命令 177 6.5 自定义网络服务 177 6.5.1 xinetd/inetd 178 6.5.2 xinetd服务配置 178 6.5.3 自定义网络服务 179 6.6 小结 180 第7章 TCP网络编程基础 181 7.1 套接字编程基础知识 181 7.1.1 套接字地址结构 181 7.1.2 用户层和内核层交互过程 183 7.2 TCP网络编程流程 184 7.2.1 TCP网络编程架构 184 7.2.2 创建网络插口函数socket() 186 7.2.3 绑定一个地址端口对bind() 189 7.2.4 监听本地端口listen 192 7.2.5 接受一个网络请求accept() 194 7.2.6 连接目标网络服务器connect() 199 7.2.7 写入数据函数write() 200 7.2.8 读取数据函数read() 201 7.2.9 关闭套接字函数close() 201 7.3 服务器/客户端的简单例子 202 7.3.1 例子功能描述 202 7.3.2 服务器网络程序 203 7.3.3 服务器读取和显示字符串 205 7.3.4 客户端的网络程序 205 7.3.5 客户端读取和显示字符串 206 7.3.6 编译运行程序 206 7.4 截取信号的例子 207 7.4.1 信号处理 207 7.4.2 信号SIGPIPE 208 7.4.3 信号SIGINT 208 7.5 小结 208 第8章 服务器和客户端信息的获取 210 8.1 字节序 210 8.1.1 大端字节序和小端字节序 210 8.1.2 字节序转换函数 212 8.1.3 一个字节序转换的例子 214 8.2 字符串IP地址和二进制IP地址的转换 217 8.2.1 inet_xxx()函数 217 8.2.2 inet_pton()和inet_ntop()函数 219 8.2.3 使用8.2.1节地址转换函数的例子 220 8.2.4 使用函数inet_pton()和函数inet_ntop()的例子 223 8.3 套接字描述符判定函数issockettype() 223 8.3.1 进行文件描述符判定的函数issockettype() 224 8.3.2 main()函数 224 8.4 IP地址与域名之间的相互转换 225 8.4.1 DNS原理 225 8.4.2 获取主机信息的函数 226 8.4.3 使用主机名获取主机信息的例子 228 8.4.4 函数gethostbyname()不可重入的例子 230 8.5 协议名称处理函数 232 8.5.1 xxxprotoxxx()函数 232 8.5.2 使用协议族函数的例子 233 8.6 小结 236 第9章 数据的IO和复用 237 9.1 IO函数 237 9.1.1 使用recv()函数接收数据 237 9.1.2 使用send()函数发送数据 239 9.1.3 使用readv()函数接收数据 240 9.1.4 使用writev()函数发送数据 240 9.1.5 使用recvmsg()函数接收数据 242 9.1.6 使用sendmsg()函数发送数据 244 9.1.7 IO函数的比较 246 9.2 使用IO函数的例子 246 9.2.1 客户端处理框架的例子 246 9.2.2 服务器端程序框架 248 9.2.3 使用recv()和send()函数 249 9.2.4 使用readv()和write()函数 251 9.2.5 使用recvmsg()和sendmsg()函数 253 9.3 IO模型 256 9.3.1 阻塞IO模型 256 9.3.2 非阻塞IO模型 257 9.3.3 IO复用 257 9.3.4 信号驱动IO模型 258 9.3.5 异步IO模型 258 9.4 select()函数和pselect()函数 259 9.4.1 select()函数 259 9.4.2 pselect()函数 261 9.5 poll()函数和ppoll()函数 262 9.5.1 poll()函数 263 9.5.2 ppoll()函数 264 9.6 非阻塞编程 264 9.6.1 非阻塞方式程序设计介绍 264 9.6.2 非阻塞程序设计的例子 264 9.7 小结 266 第10章 基于UDP协议的接收和发送 267 10.1 UDP编程框架 267 10.1.1 UDP编程框图 267

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值