<UNIX环境高级编程>--第七章


1进程终止

进程正常终止:

  1. #include<stdlib.h> 
  2.  
  3. void exit(int status); 
  4.  
  5. void _Exit(int status); 
  6.  
  7. #include<unistd.h> 
  8.  
  9. void _exit(int status); 
  1. #include<stdlib.h>  
  2.   
  3. void exit(int status);  
  4.   
  5. void _Exit(int status);  
  6.   
  7. #include<unistd.h>  
  8.   
  9. void _exit(int status);  


区别:_exit和_Exit函数调用的时候立即进入内核,而exit函数则要进行一些清理操作。在进入内核。

如图所示:

exit()函数与_exit()函数最大的区别就在于exit()函数在调用exit系统调用之前要检查文件的打开情况,把文件缓冲区中的内容写回文件,就是图中的“清理I/O缓冲”一项。
在Linux 的标准函数库中,有一套称作“高级I/O”的函数,我们熟知的printf()、fopen()、fread()、fwrite()都在此列,它们也被称作“缓冲I/O(buffered I/O)”,其特征是对应每一个打开的文件,在内存中都有一片缓冲区,每次读文件时,会多读出若干条记录,这样下次读文件时就可以直接从内存的缓冲区中读取,每次写文件的时候,也仅仅是写入内存中的缓冲区,等满足了一定的条件(达到一定数量,或遇到特定字符,如换行符\n和文件结束符EOF),再将缓冲区中的内容一次性写入文件,这样就大大增加了文件读写的速度,但也为我们编程带来了一点点麻烦。如果有一些数据,我们认为已经写入了文件,实际上因为没有满足特定的条件,它们还只是保存在缓冲区内,这时我们用_exit()函数直接将进程关闭,缓冲区中的数据就会丢失,反之,如果想保证数据的完整性,就一定要使用exit()函数。

看下面的例子

  1. /* exit2.c */ 
  2. #include<stdlib.h> 
  3. main() 
  4. {    
  5.     printf("output begin\n"); 
  6.     printf("content in buffer"); 
  7.     exit(0); 
  8. }  
  1. /* exit2.c */  
  2. #include<stdlib.h>  
  3. main()  
  4. {     
  5.     printf("output begin\n");  
  6.     printf("content in buffer");  
  7.     exit(0);  
  8. }   

编译并运行:

$gcc exit2.c -o exit2
$./exit2output begin
content in buffer

  1. /* _exit1.c */ 
  2. #include<unistd.h> 
  3. main() 
  4. {    
  5.     printf("output begin\n"); 
  6.     printf("content in buffer"); 
  7.     _exit(0); 
  8. } <p>编译并运行:</p><p>$gcc _exit1.c -o _exit1 
  9. $./_exit1 
  10. output begin</p> 
  1. /* _exit1.c */  
  2. #include<unistd.h>  
  3. main()  
  4. {     
  5.     printf("output begin\n");  
  6.     printf("content in buffer");  
  7.     _exit(0);  
  8. } <p>编译并运行:</p><p>$gcc _exit1.c -o _exit1  
  9. $./_exit1  
  10. output begin</p>  

2.c程序的启动与终止

注意内核使程序执行的唯一方法是调用一个exec函数。进程自愿终止的唯一方法就是显示的或者饮食的调用exit ,_exit ,_Exit函数。

3.c程序在linux中

每个程序在系统中,都会有一个环境表。

当我们运行一个程序的时候,c程序有以下部分组成。

  • 正文段,这是由CPU执行的机器指令部分。通常,正文段是可共享的所以即使是频繁的执行的程序,在存储忠也只需要一个副本,另外,正文段常常是只读的。以防止由于意外而修改自身的指令。
  • 初始化数据段。它包含了程序中需要明确的赋初值的变量。如任何函数之外声明的 int maxcount=99;使此变量带有初值存放在初始化数据段中。
  • 非初始化数据段。通常称为bss段。在程序开始执行前,内核将此段忠的数据初始化为0或者空指针。出现在任何函数外的C声明。long sum[100];使此变量存放在非初始化数据段中。
  • 栈,自动变量以及每次函数调用时候所需要保存的信息都存放此段中。每次调用函数时候,其返回地址以及调用者的环境信息都存放再栈中。然后最近被调用的函数在栈上为其自动和临时变量分配的存储空间。通过以这种方式使用栈,可以递归调用C函数。函数每次调用自身的时候,就使用一个新的栈帧。因此一个函数调用示例忠的变量及不会影响另个一个函数调用的实例变量。
  • 堆。通常在堆中进行动态存储分配。对位于非初始化数据段和栈之间。

4.共享库

共享库使得可执行文件中不再需要包含公用的库例程。而只需要在所有进程都可引用的存储区忠维护这种库例程的一个副本。程序在第一次执行或者第一次调用某个库函数 的时候,用动态链接的方法见程序与共享库函数相链接。

当我们使用

  1. size  

命令查看的时候,就可以看到。

5.存储器分配

三个函数的声明分别是: 

  1. void* realloc(void* ptr, unsigned newsize);  
  2. void* malloc(unsigned size);  
  3. void* calloc(size_t nelem, size_t elsize);  
  1. void* realloc(void* ptr, unsigned newsize);   
  2. void* malloc(unsigned size);   
  3. void* calloc(size_t nelem, size_t elsize);   


都在stdlib.h函数库内

原型:extern void *realloc(void *mem_address, unsigned int newsize);

用法:#include <alloc.h> 
功能:改变mem_address所指内存区域的大小为newsize长度。

说明:如果重新分配成功则返回指向被分配内存的指针,否则返回空指针NULL。 
        当内存不再使用时,应使用free()函数将内存块释放。

原型:extern void *malloc(unsigned int num_bytes);
用法:#include <alloc.h>

功能:分配长度为num_bytes字节的内存块

说明:如果分配成功则返回指向被分配内存的指针,否则返回空指针NULL。 
        当内存不再使用时,应使用free()函数将内存块释放。

原型:extern void *calloc(int num_elems, int elem_size);
用法:#include <alloc.h> 
功能:为具有num_elems个长度为elem_size元素的数组分配内存 
说明:如果分配成功则返回指向被分配内存的指针,否则返回空指针NULL。 
        当内存不再使用时,应使用free()函数将内存块释放。

区别:

1、calloc在动态分配完内存后,自动初始化该内存空间为零,而malloc不初始化,里边数据是随机的垃圾数据

2、realloc是给一个已经分配了地址的指针重新分配空间,参数ptr为原有的空间地址,newsize是重新申请的地址长度



  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
本书全面介绍了UNIX系统的程序设计界面—系统调用界面和标准C提供的许多函数。 本书的前15着重于理论知识的阐述,主要内容包括UNIX文件和目录、进程环境、进程控制、 进程间通信以及各种I/O。在此基础上,分别按介绍了多个应用实例,包括如何创建数据函数, PostScript 打印机驱动程序,调制解调器拨号器及在伪终端上运行其他程序的程序等。 本书内容丰富权威, 概念清晰精辟,一直以来被誉为UNIX编程的“圣经”,对于所有UNIX程序员—无论是初学者还是专家级人士 —都是一本无价的参考书籍。 目 录 译者序 译者简介 前言 第1 UNIX基础知识 1 1.1 引言 1 1.2 登录 1 1.2.1 登录名 1 1.2.2 shell 1 1.3 文件和目录 2 1.3.1 文件系统 2 1.3.2 文件名 2 1.3.3 路径名 2 1.3.4 工作目录 4 1.3.5 起始目录 4 1.4 输入和输出 5 1.4.1 文件描述符 5 1.4.2 标准输入、标准输出和标准 出错 5 1.4.3 不用缓存的I/O 5 1.4.4 标准I/O 6 1.5 程序和进程 7 1.5.1 程序 7 1.5.2 进程和进程ID 7 1.5.3 进程控制 7 1.6 ANSI C 9 1.6.1 函数原型 9 1.6.2 类属指针 9 1.6.3 原始系统数据类型 10 1.7 出错处理 10 1.8 用户标识 11 1.8.1 用户ID 11 1.8.2 组ID 12 1.8.3 添加组ID 12 1.9 信号 12 1.10 UNIX时间值 14 1.11 系统调用和函数 14 1.12 小结 16 习题 16 第2 UNIX标准化及实现 17 2.1 引言 17 2.2 UNIX标准化 17 2.2.1 ANSI C 17 2.2.2 IEEE POSIX 18 2.2.3 X/Open XPG3 19 2.2.4 FIPS 19 2.3 UNIX实现 19 2.3.1 SVR4 20 2.3.2 4.3+BSD 20 2.4 标准和实现的关系 21 2.5 限制 21 2.5.1 ANSI C限制 22 2.5.2 POSIX限制 22 2.5.3 XPG3限制 24 2.5.4 sysconf、pathconf 和fpathconf 函数 24 2.5.5 FIPS 151-1要求 28 2.5.6 限制总结 28 2.5.7 未确定的运行时间限制 29 2.6 功能测试宏 32 2.7 基本系统数据类型 32 2.8 标准之间的冲突 33 2.9 小结 34 习题 34 第3 文件I/O 35 3.1 引言 35 3.2 文件描述符 35 3.3 open函数 35 3.4 creat函数 37 3.5 close函数 37 3.6 lseek函数 38 3.7 read函数 40 3.8 write函数 41 3.9 I/O的效率 41 3.10 文件共享 42 3.11 原子操作 45 3.11.1 添加至一个文件 45 3.11.2 创建一个文件 45 3.12 dup和dup2函数 46 3.13 fcntl函数 47 3.14 ioctl函数 50 3.15 /dev/fd 51 3.16 小结 52 习题 52 第4 文件和目录 54 4.1 引言 54 4.2 stat, fstat和lstat函数 54 4.3 文件类型 55 4.4 设置-用户-ID和设置-组-ID 57 4.5 文件存取许可权 58 4.6 新文件和目录的所有权 60 4.7 access函数 60 4.8 umask函数 62 4.9 chmod和fchmod函数 63 4.10 粘住位 65 4.11 chown, fchown和 lchown函数 66 4.12 文件长度 67 4.13 文件截短 68 4.14 文件系统 69 4.15 link, unlink, remove和rename 函数 71 4.16 符号连接 73 4.17 symlink 和readlink函数 76 4.18 文件的时间 76 4.19 utime函数 78 4.20 mkdir和rmdir函数

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值