Linux操作系统-进程和信号(1)

来源:互联网 发布:在网络上怎么赚钱 编辑:程序博客网 时间:2024/04/29 07:39

Linux操作系统—进程和信号(1)

分类:Linux操作系统

Linux进程环境

程序的入口

  C程序总是从main函数开始执行。来好好了解一下main函数吧(C语言课上学的简直连皮毛都达不到)main函数的原型如下:

int main(int argc, char *argv[]);

  其中,argc是命令行参数的数目,argv是指向命令参数的各指针所构成的数组。下面是一个例子,作用是将命令行传递给程序的参数打印出来。

#include <stdio.h>int main(int argc, char *argv[]){    int i;    for (i = 0; i < argc; i++)        printf("argv[%d] : %s\n", i, argv[i]);    return 0;}

  编译并运行

biantiao@lazybone1994-ThinkPad-E430:~/桌面$ gcc -o main main.cbiantiao@lazybone1994-ThinkPad-E430:~/桌面$ ./main a.txt b.txtargv[0] : ./mainargv[1] : a.txtargv[2] : b.txtbiantiao@lazybone1994-ThinkPad-E430:~/桌面$

进程的终止

  正常终止的情况
1. 从main返回
2. 调用exit
3. 调用_exit

  异常终止的情况
1. 被一个系统信号终止
2. 调用abort,它产生SIGABRT信号,是一种异常终止的特例

exit和_exit的区别

  eixt和_exit都用于正常终止一个程序,它们的区别是:_exit立即进入内核,exit则先执行一些清除处理(包括调用执行各终止处理程序,关闭所有标准I/O流等),然后进入内核。exit属于标准函数库,而exit是底层系统调用,它们的原型分别如下:

#include <stdlib.h>void exit(int status);
#include <unistd.h>void _exit(int status);

  exit函数会执行一个标准I/O库的清除关闭操作,即对所有打开的流调用fclose函数.

atexit函数

  上面说到了exit函数会执行一个标准I/O库的清除关闭操作,那这是怎么实现的呢?答案就是通过atexit函数实现。
  ANSI C规定,一个进程可以登记多至32个由exit自动调用的函数,这些函数被称为终止处理程序(exit handler)。登记终止处理程序要使用atexit函数,它的函数原型如下:

#include <stdlib.h>int atexit(void (*function)(void));

  atexit的参数是一个函数地址,atexit函数成功时返回0,失败时返回非0值。要注意的是exit函数以登记这些函数的相反顺序调用它们。同一函数如果多次登记,则也将被调用多次。下面是一个使用atexit函数的例子

#include <stdio.h>static void my_exit1(void);static void my_exit2(void);int main(int argc, char *argv[]){    if (atexit(my_exit2) != 0){            /* 登记my_exit2 */        puts("Register my_exit2 failed.");        return -1;    }    if (atexit(my_exit1) != 0){            /* 登记my_exit1 */        puts("Register my_exit1 failed.");        return -1;    }    puts("Main is done.");    return 0;}static void my_exit1(void){    puts("First exit handler.");}static void my_exit2(void){    puts("Second exit handler.");}

  编译并运行,要注意的是exit以与登记这些函数的相反顺序调用它们

biantiao@lazybone1994-ThinkPad-E430:~/桌面$ gcc -o atexit atexit.cbiantiao@lazybone1994-ThinkPad-E430:~/桌面$ ./atexitMain is done.First exit handler.Second exit handler.biantiao@lazybone1994-ThinkPad-E430:~/桌面$

环境表

  每个进程在启动时都能收到一张环境表。与命令行的参数一样,环境表也是一个字符指针数组,其中每个指针包含一个以null结束的字符串地址。全局变量environ记录了该指针数组的地址。
extern char **environ;
  全局变量environ称为环境指针,其所指向的数组称为环境表,数组中的每个指针指向的字符串称为环境字符串。环境字符串具有约定的形式如”name=value”的格式。

C程序的存储空间布局

  C程序的存储空间一般由一下几个部分组成
- 正文段:由CPU执行的机器指令构成.通常,正文段共享的,所以同时启动一个程序的多个进程,在内存中只有一个正文段的副本.另外,正文段常常是只读的,这可以防止程序由于意外事故而修改自身的指令.
- 初始化数据段:由程序中已赋值的静态变量构成.
- 非初始化数据段:常称为bss段,在程序开始执行之前,内核将此段初始化为0.
- 栈:自动变量以及每次函数调用时所需保存的场景信息存放在此段中.另外函数调用时也使用栈来传递参数,被调用的函数则在栈上为其自动变量和临时变量分配存储空间
- 堆:通常在堆中进行动态分配。堆位于非初始化数据段顶和栈底之间

  可以使用size命令查看一个可执行程序的正文段,数据段和bss段的字节数

静态库和共享库

  什么是库?库就是可复用的二进制可执行代码的有序集合
  Linux下有两种类型的库,分别是静态库和共享库。两种的一个重要区别在于其中的代码被载入的时刻不同。
- 使用静态库的程序,在编译链接过程即载入静态库的代码并将静态库的代码置入编译出的可执行程序。
- 使用共享库的程序,在编译链接过程中仅对共享库作简单引用,在程序运行时才将共享库的代码载入内存。

  在Linux下,库文件一般放在/usr/lib和/lib下。静态库的名字一般为libxxxx.a,其中xxxx是该库的名字。动态库的名字一般为libxxxx.so.major.minor,其中xxxx是该库的名称,major是主版本号,minor是次版本号。

0 0