Linux/UNIX之进程环境
进程环境
进程终止
有8种方式使进程终止,当中5中为正常终止,它们是
1) 从main返回
2) 调用exit
3) 调用_exit或_Exit
4) 最后一个线程从其启动例程返回
5) 最后一个线程调用pthread_exit
异常终止有3中方式
6) 调用abort
7) 接到一个信号并终止
8) 最后一个线程对取消请求做出对应
exit函数
#include <stdlib.h>
void exit(int status);
void _Exit(int status);
#include <unistd.h>
void _exit(int status);
三个函数都带有一个整形參数,成为终止状态。
exit函数总是先运行一个标准I/O库的清理关闭操作:为所以打开流调用fclose函数,这会造成所以缓冲区的输出数据都被冲洗。
exit(0)等价于return(0)。
atexit函数
依照ISO C的规定,一个进程能够登记多达32个函数,这些函数将由exit自己主动调用。我们称这些函数为终止处理程序,并调用atexit函数来登记这些函数。
#include <stdlib.h>
int atexit(void (*function)(void));
当中,atexit的參数是一个函数地址,当调用此函数时无需向它传送不论什么參数,也不期望它返回一个值。exit调用这些函数的顺序与他们被atexit登记的顺序相反。同一函数如登记多次,则也会被调用多次。例如以下是使用atexit的程序。
#include "stdlib.h"
#include "stdio.h"
static void my_exit1(void);
static void my_exit2(void); int main(void)
{
if (atexit(my_exit2) != 0)
perror("can't register my_exit2"); if (atexit(my_exit1) != 0)
perror("can't register my_exit1");
if (atexit(my_exit1) != 0)
perror("can't register my_exit1"); printf("main is done\n");
return(0);
}
static void my_exit1(void)
{
printf("first exit handler\n");
} static void my_exit2(void)
{
printf("second exit handler\n");
}
输出结果例如以下:
main is done
first exit handler
first exit handler
second exit handler
命令行參数
内核是程序运行的唯一方法是调用exec函数。当运行一个程序时,exec的进程可将命令行參数传递给该新程序。
C程序的存储空间布局
正文段:这是由CPU运行的机器指令部分。通常正文段是能够共享的。
初始化数据段:通常将此段成为数据段。包括程序中明白赋初值的全局变量或静态变量。
非初始化数据段:通常称此段为BBS段(block startedby ymbol),未赋初值的全局变量或静态变量。在程序运行之前,内核将此段的数据初始化为0或空指针。
栈:自己主动变量以及每次函数调用时所需保存的信息都存放在此段中。
堆:通常在堆中进行动态存储分配。
C程序典型的存储安排例如以下所看到的:
用size命令报告正文段、数据段和bbs段的长度。
环境表和环境变量
环境表
每个程度都会接收到一张环境表。环境表是一个字符指针数组,当中每个指针包括一个以null结束的C字符串的地址。全局变量environ则包括了该指针数组的地址:
extern char**environ
比如,假设该环境包括5个字符串,则其示意图例如以下
当中每一个字符串结尾都显示的有一个null字符。我们称environ为环境指针,指针数组为环境表,当中各个指针所指字符串为环境字符串。
环境变量
环境字符串的形式通常例如以下:
name = value
ISO C定义了一个函数getenv用于取环境变量值:
#include <stdlib.h>
char *getenv(const char *name);
此函数返回一个指针,指向name = value字符串中的value。未找到返回NULL。
#include <stdlib.h>
int putenv(char *string);
int setenv(const char *name, const char*value, int overwrite);
int unsetenv(const char *name);
putenv取形式为name = value的字符串,将其放到环境表中。假设name已近存在,则先删除原定义。
setenv将name设置为value。
unsetenv删除name的定义。
环境表和环境字符串通常存储在空间的顶部(栈之上)
setjmp和longjmp
C语言中goto是不能跨越函数的,运行这类跳转功能的函数是setjmp和longjmp。
#include <setjmp.h>
int setjmp(jmp_buf env);
void longjmp(jmp_buf env, int val);
通过程序来看看自己主动变量、全局变量、寄存器变量、静态变量和易失变量的不同情况:
#include <stdio.h>
#include <setjmp.h> static void f1(int, int, int, int);
static void f2(void); static jmp_buf jmpbuffer;
static int globval; int main(void)
{
int autoval;
register int regival;
volatile int volaval;
static int statval; globval = 1; autoval = 2; regival = 3; volaval = 4; statval = 5; if (setjmp(jmpbuffer) != 0) {
printf("after longjmp:\n");
printf("globval = %d, autoval = %d, regival = %d,"
" volaval = %d, statval = %d\n",
globval, autoval, regival, volaval, statval);
exit(0);
} /*
* Change variables after setjmp, but before longjmp.
*/
globval = 95; autoval = 96; regival = 97; volaval = 98;
statval = 99; f1(autoval, regival, volaval, statval); /* never returns */
exit(0);
} static void
f1(int i, int j, int k, int l)
{
printf("in f1():\n");
printf("globval = %d, autoval = %d, regival = %d,"
" volaval = %d, statval = %d\n", globval, i, j, k, l);
f2();
} static void
f2(void)
{
longjmp(jmpbuffer, 1);
}
其运行结果例如以下:
in f1():
globval = 95, autoval = 96, regival = 97,volaval = 98, statval = 99
after longjmp:
globval = 95, autoval = 2, regival = 3,volaval = 98, statval = 99
可见全局变量、静态变量和易失变量不受影响,自己主动变量和寄存器变量是否变化是不确定的(虽然这里显示恢复setjmp的值)。
getrlimit和setrlimit函数
#include <sys/time.h>
#include <sys/resource.h>
int getrlimit(int resource, struct rlimit*rlim);
int setrlimit(int resource, const structrlimit *rlim);
每一个进程都有一组资源限制,当中一些能够用getrlimit和setrlimit函数查询和更改。进程的资源限制一般是在系统初始化时由进程0建立的,然后由每一个后序进程继承。
Linux/UNIX之进程环境的更多相关文章
- Linux/Unix分配进程ID的方法以及源代码实现
在Linux/Unix系统中.每一个进程都有一个非负整型表示的唯一进程ID.尽管是唯一的.可是进程的ID能够重用.当一个进程终止后,其进程ID就能够再次使用了. 大多数Linux/Unix系统採用延迟 ...
- 编写Linux/Unix守护进程
原文: http://www.cnblogs.com/haimingwey/archive/2012/04/25/2470190.html 守护进程在Linux/Unix系统中有着广泛的应用.有时,开 ...
- Linux下的进程环境
僵尸进程.孤儿进程.守护进程.进程组.会话.前台进程组.后台进程组 1,僵尸进程 子进程结束,父进程没有明确的答复操作系统内核:已收到子进程结束的消息.此时操作系统内核会一直保存该子进程的部分PCB信 ...
- (五) 一起学 Unix 环境高级编程 (APUE) 之 进程环境
. . . . . 目录 (一) 一起学 Unix 环境高级编程 (APUE) 之 标准IO (二) 一起学 Unix 环境高级编程 (APUE) 之 文件 IO (三) 一起学 Unix 环境高级编 ...
- Linux Unix 环境变量设置实例
背景 从第一次写Hello World我们便开始接触环境变量.这最基础的系统设置是必须要掌握的,尤其在是Linux/Unix系统中.比如,哪天某个Java进程出现问题,我们想分析一下其线程堆栈,却发现 ...
- Supervisor安装与配置(Linux/Unix进程管理工具)
原文链接:http://blog.csdn.net/xyang81/article/details/51555473 Supervisor(http://supervisord.org/)是用Pyth ...
- Supervisor(Linux/Unix进程管理工具)安装与配置
参考链接:https://blog.csdn.net/xyang81/article/details/51555473 Supervisor(http://supervisord.org/)是用Pyt ...
- Linux进程环境
Linux下C程序都是main开始的,main函数的原型是: int main(int argc, char **argv) 其中argc是命令行参数的数目,argc是指向参数的各个指针所构成的数组. ...
- Unix环境高级编程(五)进程环境
本章主要介绍了Unix进程环境,包含main函数是如何被调用的,命令行参数如何传递,存储方式布局,分配存储空间,环境变量,进程终止方法,全局跳转longjmp和setjmp函数及进程的资源限制. ma ...
随机推荐
- swift class extension 与继承
1.扩展中无法继承重写已有函数,不能添加函数. Extensions can add new functionality to a type, but they cannot override exi ...
- CAD使用GetAllAppName读所有名称(com接口)
主要用到函数说明: MxDrawEntity::GetAllAppName 得到所有扩展数据名称,详细说明如下: 参数 说明 [out, retval] IMxDrawResbuf** ppRet 返 ...
- 并发2-Synchronized
一.Synchronized的概念 是利用锁的机制来实现同步的. 锁机制有如下两种特性: 互斥性:即在同一时间只允许一个线程持有某个对象锁,通过这种特性来实现多线程中的协调机制,这样在同一时间只有一个 ...
- 字符串匹配算法之BM算法
BM算法,全称是Boyer-Moore算法,1977年,德克萨斯大学的Robert S. Boyer教授和J Strother Moore教授发明了一种新的字符串匹配算法. BM算法定义了两个规则: ...
- CF147B Smile House
题目大意:给定一个有向图,其中边有边权.求点数最少的正环的点数. 题解:建立矩阵,处理其二进制上每一位的状态.时间O(n^3*log(n)). 代码: #include<cstdio> # ...
- 如何在 CentOS 7 上生成 SSL 证书为 Nginx 加密
本文首发:开发指南:如何在 CentOS 7 上安装 Nginx Let’s Encrypt 是由 Internet Security Research Group (ISRG) 开发的一个自由.自动 ...
- 理解javascript中的Array类型
引子: 从事前端开发有段时间了,个人观点:想在前端开发这条路上走的更远,不仅要学好HTML&HTML5.CSS&CSS3,最重要的就是要学好javascript了.所以打好javasc ...
- jsp学习之如何在web层创建Servlet
jsp动态网页的文件目录结构如下: 1.src下存放java代码 2.包web_xx为web层 3.webcontent里面是jsp文件 jsp页面中的请求交付给servlet处理,在实际中 jsp的 ...
- NYOJ-769乘数密码,逆元解法;
乘数密码 时间限制:1000 ms | 内存限制:65535 KB 难度:1 -> Link <- 简单代替密码的第二种,比移位密码稍微复杂点,不过鉴于NYOJ,是完全可以 ...
- hihoCoder#1120 小Hi小Ho的惊天大作战:扫雷·三
原题地址 看上去非常复杂, 实际上是这一系列最简单的一步,本质上是个搜索过程,相比于前一道题,可以不用策略三,而且题目的数据规模超级小,所以暴力搜索就能过. 把尚未确定的点放在一个unsettled列 ...