unix环境高级编程-7-进程环境

这两天都没写博客,主要是我想改变一下方法吧。不想一节节的读了,我想把一个整章看好了,然后进行思考,然后再进行编辑写在博客里。我觉得这样可以省的时间来思考,写程序。把每章中最主要的部门拿出来。算是第二遍复习。可以加深我的印象吧。

1进程终止

进程正常终止:

#include<stdlib.h>

void exit(int status);

void _Exit(int status);

#include<unistd.h>

void _exit(int status);


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

如图所示:unix环境高级编程-7-进程环境_第1张图片

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

看下面的例子

/* exit2.c */
#include<stdlib.h>
main()
{	
	printf("output begin\n");
	printf("content in buffer");
	exit(0);
} 

编译并运行:

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

/* _exit1.c */
#include<unistd.h>
main()
{	
	printf("output begin\n");
	printf("content in buffer");
	_exit(0);
} 

编译并运行:

$gcc _exit1.c -o _exit1 $./_exit1 output begin

2.c程序的启动与终止

unix环境高级编程-7-进程环境_第2张图片

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

3.c程序在linux中

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

unix环境高级编程-7-进程环境_第3张图片

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

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

unix环境高级编程-7-进程环境_第4张图片

4.共享库

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

当我们使用

size

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

5.存储器分配

三个函数的声明分别是:

void* realloc(void* ptr, unsigned newsize); 
void* malloc(unsigned size); 
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是重新申请的地址长度

更多内容,欢迎访问:http://blog.csdn.net/wallwind

你可能感兴趣的:(unix环境高级编程-7-进程环境)