读书之《Linux环境下C编程指南》

来源:互联网 发布:发发棋牌源码 编辑:程序博客网 时间:2024/05/17 01:02

学习本书是在学习国嵌视频的基础上进行的,相似的内容就不再总结了。

目 录

第1章 C语言基础和Linux系统概述 1
1.1 C语言基础 2
1.1.1 C语言概述 2
1.1.2 数据类型 2
1.1.3 运算符和表达式 9
1.1.4 C程序语句 10
1.1.5 函数 15
1.1.6 编译预处理 16
1.2 Linux系统概述 18
1.2.1 Linux系统的发展历史 18
1.2.2 Linux系统特点及主要功能 19
1.2.3 Linux系统的主要产品 20
1.3 本章小结 20

第2章 vim与Emacs编辑器 21
2.1 vim简介 22
2.1.1 启动与退出vim 22
2.1.2 命令行模式的操作 23
2.1.3 命令行模式切换到输入模式 25
2.1.4 最后行模式的操作 26
2.2 Emacs简介 26
2.2.1 Emacs编辑器的运行和结束 26
2.2.2 基本操作 27
2.3 Emacs的C模式 29
2.3.1 自动缩进 29
2.3.2 注释 29
2.3.3 预处理扩展 29
2.3.4 自动状态 30
2.3.5 使用Emacs进行编译和调试 30
2.4 本章小结 30

第3章 gcc编译器 31
3.1 gcc编译器简介 32
3.1.1 Hello World程序 32
3.1.2 gcc选项概述 33
3.1.3 警告 35
3.1.4 优化gcc 36
3.1.5 调试标记 40
3.1.6 使用高级gcc选项 42
3.2 gcc编译流程简介 44
3.2.1 C预处理器 cpp 44
3.2.2 GUN连接器 ld 44
3.2.3 GUN汇编器 as 45
3.2.4 文件处理器 ar 45
3.2.5 库显示 ldd 45
3.3 其他编译调试工具 45
3.4 本章小结 46

第4章 调试工具gdb 47
4.1 gdb符号调试器简介 48
4.2 gdb功能详解及其应用 48
4.2.1 调试步骤 49
4.2.2 显示数据命令 57
4.2.3 使用断点 62
4.2.4 使用观察窗口 65
4.2.5 查看栈信息 68
4.2.6 查看源程序 70
4.2.7 查看运行时数据 73
4.2.8 改变程序的执行 81
4.2.9 core dump分析 84
4.3 其他调试工具 90
4.4 本章小结 90

第5章 使用make 91
5.1 makefile文件简介 92
5.2 make书写规则 94
5.2.1 规则举例 94
5.2.2 在规则中使用通配符 94
5.2.3 文件搜寻 95
5.2.4 伪目标 96
5.2.5 多目标 97
5.2.6 静态模式 97
5.2.7 自动生成依赖性 99
5.3 使用命令 100
5.3.1 显示命令 100
5.3.2 执行命令 101
5.3.3 命令出错 101
5.3.4 嵌套执行make 102
5.3.5 定义命令包 103
5.4 使用变量 104
5.4.1 变量的基础 104
5.4.2 赋值变量 105
5.4.3 变量的高级用法 107
5.4.4 追加变量值 109
5.4.5 override 指示符 110
5.4.6 多行变量 110
5.4.7 环境变量 110
5.4.8 目标变量 111
5.4.9 模式变量 112
5.5 使用条件判断 112
5.5.1 示例 112
5.5.2 语法 113
5.6 使用函数 115
5.6.1 函数的调用语法 115
5.6.2 字符串处理函数 116
5.6.3 文件名操作函数 119
5.6.4 foreach 函数 120
5.6.5 if 函数 121
5.6.6 call函数 122
5.6.7 origin函数 122
5.6.8 shell函数 123
5.6.9 控制make的函数 124
5.7 make的运行 124
5.7.1 make的退出码 124
5.7.2 指定makefile文件 124
5.7.3 指定目标 125
5.7.4 检查规则 126
5.7.5 make的参数 127
5.8 隐含规则 130
5.8.1 使用隐含规则 131
5.8.2 隐含规则一览 131
5.8.3 隐含规则使用的变量 133
5.8.4 隐含规则链 135
5.8.5 定义模式规则 136
5.8.6 隐含规则搜索算法 139
5.9 使用make更新函数库文件 140
5.9.1 函数库文件的成员 140
5.9.2 函数库成员的隐含规则 141
5.9.3 函数库文件的后缀规则 141
5.9.4 注意事项 142
5.10 高级使用 142
5.10.1 宏的使用 142
5.10.2 内部规则 147
5.10.3 make递归 150
5.10.4 依赖性的计算 150
5.11 库的使用 153
5.11.1 创建库和维护库 154
5.11.2 库的链接 155
5.12 本章小结 156

第6章 进程控制 157
6.1 进程的基本概念 158
6.1.1 进程基本介绍 158
6.1.2 进程的属性 159
6.2 进程控制的相关函数 160
6.2.1 进程的创建 160
6.2.2 进程等待 164
6.2.3 进程的终止 168
6.2.4 进程ID和进程组ID 171
6.2.5 system函数 176
6.3 多个进程间的关系 177
6.3.1 进程组 177
6.3.2 时间片的分配 178
6.3.3 进程的同步 180
6.4 线程 180
6.4.1 线程的创建 180
6.4.2 线程属性的设置 181
6.4.3 结束线程 182
6.4.4 线程的挂起 182
6.4.5 取消线程 183
6.4.6 互斥 184
6.5 本章小结 184

第7章 文件操作 187
7.1 文件系统简介 188
7.1.1 文件 188
7.1.2 文件的相关信息 190
7.1.3 文件系统 191
7.2 基于文件描述符的I/O操作 191
7.2.1 文件的创建、打开与关闭 192
7.2.2 文件的读写操作 194
7.2.3 文件的定位 198
7.3 文件的其他操作 

   修改文件权限(chown、fchown)、修改文件的访问权限(chmodchar、fchmod)
7.3.1 文件属性的修改 200

 重命名(rename)、修改文件长度(truncate、ftruncate
7.3.2 文件的其他操作 

 dup 、dup2调用,stat、fstat、lstat调用,fsync调用,flock调用,fcntl调用,select调用。
7.4 特殊文件的操作 
7.4.1 目录文件的操作 

创建mkdir,删除rmdir,打开opdir,关闭closedir,读取direct。
7.4.2 链接文件的操作 

   硬链接创建link,移除unlink。
   符号链接 symlink、readlink。

7.4.3 管道文件的操作   pipe
7.4.4 设备文件 

7.5 本章小结 211

第8章 输入输出——基于流的操作 213
8.1 流简介 214
8.2 基于流的I/O操作 215
8.2.1 流的打开和关闭 216
8.2.2 缓冲区的操作 217
8.2.3 直接输入输出 219
8.2.4 格式化输入输出 221
8.2.5 基于字符和行的输入输出 224
8.3 临时文件 227
8.4 本章小结 231

第9章 内存管理 233

9.1 静态内存与动态内存 234

静态内存,是在程序开始运行前由系统分配的内存,其分配是由编译器实现的;

动态内存,是在程序运行过程中由用户自己申请分配的内存;
9.1.1 静态内存 234
9.1.2 动态内存 236
9.2 安全性问题 236

动态内存会引起一些问题,如溢出、内存泄露等。

溢出的解决办法:在用户程序中,根据缓冲区的大小截断所输入的数据。
9.3 内存管理操作 237
9.3.1 动态内存的分配 237

void *malloc(size_t size)

void* calloc(size_t nelem, size_telsize);
9.3.2 动态内存的释放 238

void free(void *pointer)
9.3.3 调整动态内存的大小 239

void* realloc(void* ptr, unsigned newsize);
9.3.4 分配堆栈 240

void* alloca(size_t size);
9.3.5 内存锁定 241

为了更好地使用系统的资源,当一定内存区域在一定时间里未被使用时,系统内核就会将其中的内容暂时置换到磁盘上去,稀释此内存区域用来存放其它数据。如果用户不希望某块内存区域的数据被置换到磁盘上去,就可以对该区域进行内存锁定。

int  mlock();   //锁定某一内存区域

int  munlock ();//解除某一内存区域的锁定

int mlockall();//一次锁定多个内存区域

int munlockall ();//解除所有内存区域的锁定

 

http://www.lupaworld.com/article-218039-1.html
9.4 使用链表 241

在许多情况下,用户无法预知数据的大小,因此也就无法申请相应的内存空间,可以使用链表将其分块保存。

链表是一种动态的进行存储分配的结构,链表中的每个元素都是一个结构/链表的节点。每个结点包括两个部分:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域。


9.5 内存映像I/O 244

内存映像其实在内存中创建一个与外存中文件完全相同的映像。用户可以将整个文件映射到内存中,也可以将文件的一部分映射到内存中。使用操作内存的方法对文 件进行操作。系统会将内存映像文件所做的改动反映到真实文件中去。

9.5.1 创建内存映像文件 245

首先是创建内存映像文件的系统调用mmap()函数,其函数原型为:

  #include <sys/types.h>

  #include <sys/mman.h>

  void *mmap(void *start,size_t length,int prot,int flags,int fd,off_t offset); mmap函数定义在/usr/include/sys/mman.h中;

  此函数用于将一个文件或它的一部分映射到内存中。参数start是一个void指针,表示希望将文件映射到此指针指向的位置,通常为NULL;参数 length定义内存映像文件所占用的内存空间大小,以字节计;参数prot表示内存映像文件的安全属性,它的可使用的选项见表1,注意和open函数中 的flags属性保持一致;参数flags是内存映像的标志,相关的标志见表2;参数fd是要映射的文件的描述符;参数offset表示所映射的数据内容 距离文件头的偏移量。

  当调用成功时,返回值为指向内存映像起始地址的指针;当调用失败时,返回值为-1。

  表1 prot的取值及其含义

  prot 含义

  PROT_EXEC 被映像内存可能含义机器码,可被执行

  PROT_NONE 映像内存不允许访问

  PROT_READ 映像内存可读

  PROT_WRITE 映像内存可写

  表2 flags的取值及其含义

  Flags 含义

  MAP_FIXED 若无法在指定位置建立内存映像文件,则出错返回

  MAP_PRIVATE 对内存映像文件所做操作不反映到外存文件中

  MAP_SHARED 对内存映像文件所做操作都将被保存到外存文件中


9.5.2 撤销内存映像文件 245

#include <sys/types.h>

  #include <sys/mman.h>

  int munmap(void *start,size_t length);

  参数start表示要撤销的内存映像文件的起始地址;参数length表示要撤销的内存映像文件的大小。调用成功时,返回值为0;调用失败时返回值为 -1,并将errno设置为相应值。


9.5.3 将内存映像写入外存 246

#include <sys/types.h>

  #include <sys/mman.h>

  int msync(const void *start,size_t length,int flags);

  参数start表示要保存到外存的那些源文件的起始地址;参数length表示内存映像文件的大小;参数flags设置了函数的相应操作,其具体选项见表 3。

  表3 flags的取值及其含义

  flags 含义

  MS_ASYNC 调用一个写操作并返回

  MS_INVALIDATE 映像到相同文件的内存映像数据更新

  MS_SYNC 完成写操作后函数返回

通过/dev/mem设备文件和mmap系统调用,可以将线性地址描述的物理内存映射到进程的地址空间,然后就可以直 接访问这段内存了。
9.5.4 改变内存映像文件的属性 248
9.6 本章小结 249

    应用实例:

  1. 源代码:

  /*

  file: read.c

  function: Read the the first 5 bytes of the memory and then Write it with "HELLO"

  */

  #include <stdio.h>

  #include <unistd.h>

  #include <sys/mman.h>

  #include <sys/types.h>

  #include <sys/stat.h>

  #include <fcntl.h>

  int main (int args, char* arg[])

  {

  int i;

  int fd;

  char* mem;

  char *buff = "HELLO";

  //open /dev/mem with read and write mode

  if ((fd = open ("/dev/mem", O_RDWR)) < 0)

  {

  perror ("open error");

  return -1;

  }

  //map physical memory 0-10 bytes

  mem = mmap (0, 10, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);

  if (mem == MAP_FAILED) {

  perror ("mmap error:");

  return 1;

  }

  //Read old value

  for (i = 0; i < 5; i++)

  {

  printf("\nold mem[%d]:%d", i, mem[i]);

  }

  //write memory

  memcpy(mem, buff, 5);

  //Read new value

  for (i = 0; i<5 ; i++)

  {

  printf("\nnew mem[%d]:%c", i, mem[i]);

  }

  printf("\n";

  munmap (mem, 10); //destroy map memory

  close (fd); //close file

  return 0;

  }

  2.编译、运行:

  #gcc -o read read.c

摘自:http://linux.chinaitlab.com/c/819949_2.html

第10章 信号及信号处理 251
10.1 信号及其使用简介 252
10.1.1 信号简介 252
10.1.2 信号的使用 254
10.2 信号操作的相关系统调用 255
10.2.1 信号处理 255
10.2.2 信号的阻塞 263
10.2.3 发送信号 268
10.3 信号处理的潜在危险 276
10.4 本章小结 277

第11章 进程间通信 279
11.1 进程间通信简介 280
11.2 共享内存和信号量 280
11.2.1 SYSV子系统的基本概念 280
11.2.2 共享内存 282
11.2.3 信号量 288
11.3 管道通信 298
11.3.1 管道的创建和关闭 299
11.3.2 管道的读写操作 300
11.4 命名管道 301
11.4.1 命名管道的创建 302
11.4.2 命名管道的使用 302
11.5 消息队列 306
11.5.1 消息队列的创建与打开 308
11.5.2 向消息队列中发送消息 308
11.5.3 从消息队列中接收消息 308
11.5.4 消息队列的控制 309
11.6 本章小结 311

第12章 网络编程 313
12.1 网络编程基本原理 314
12.1.1 计算机网络体系结构模式 314
12.1.2 TCP/IP协议 315
12.1.3 客户机/服务器模式 316
12.1.4 套接口编程基础 320
12.1.5 IP地址转换 332
12.2 TCP套接口编程 336
12.2.1 基于TCP的客户机/服务器模式 337
12.2.2 信号处理 343
12.2.3 高级技术 345
12.3 UDP套接口编程 354
12.3.1 基于UDP的客户机/服务器模式 354
12.3.2 主要系统调用函数 355
12.3.3 基于UDP套接口编程实例 355
12.3.4 可靠性问题 358
12.3.5 UDP套接口的连接 360
12.4 原始套接口编程 361
12.4.1 基本形式和操作 361
12.4.2 原始套接口编程实例 363
12.5 网络编程实例 368
12.6 本章小结 372

第13章 底层终端编程 373
13.1 底层终端编程 374
13.1.1 属性控制 374
13.1.2 使用terminfo 377
13.2 伪终端 379
13.3 本章小结 380