Unix环境高级编程(五)进程环境
本章主要介绍了Unix进程环境,包含main函数是如何被调用的,命令行参数如何传递,存储方式布局,分配存储空间,环境变量,进程终止方法,全局跳转longjmp和setjmp函数及进程的资源限制。
main函数的原型为int main(int argc,char *argv[]);其中argc是命令行参数的数目,argv是指向参数的各个指针构成的数组。当内核执行C程序时,使用一个exec函数,在调用main函数前线调用一个特殊的启动例程,从内核获取命令行参数和环境变量。
进程终止分为正常终止和异常终止。正常终止包括:(1)从main返回,(2)调用exit();(3)调用_exit或者_Exit();(4)最后启动一个线程从其启动例程返回;(5)最后一个线程调用pthread_exit。异常终止包括:(1)调用abort();(2)接收到一个信号并终止;(3)最后一个线程对取消请求做出响应。
1、exit函数系列:_exit和_Exit函数立即进入内核,而exit函数则执行清理处理(如关闭标准I/O流,执行各终止处理程序)。在main函数执行return (0)与exit(0)是等价的。
#include <unistd.h>
void _exit(int status);
#include <stdlib.h>
void exit(int status);
void _Exit(int status);
2、atexit函数,用来登记终止处理程序,一个进程可以登记多达32个函数,这些函数将有exit自动调用,调用顺序与登记顺序相反,同一个函数可以登记多次,则也会被调用多次。函数原型如下:
#include <stdlib.h>
int atexit(void (*function)(void)); //成功返回0,否则返回非0值
一个C程序启动和终止的过程如下图所示:
内核使程序执行的唯一方法是调用一个exec函数,终止的唯一方法是显式或者隐式地通过exit函数调用_exit()或_Exit(),也可以非自愿的由一个信号使其终止。
写个程序进程练习,程序如下:
1 #include <stdio.h>
2 #include <stdlib.h>
3
4 void exit_func1();
5 void exit_func2();
6
7 int main()
8 {
9 //登记终止处理函数
10 atexit(exit_func2);
11 atexit(exit_func1);
12 atexit(exit_func2);
13 printf("Test exit and atexit.\n");
14 exit(0);
15 }
16
17 void exit_func1()
18 {
19 printf("exit_func1() is called.\n");
20 }
21 void exit_func2()
22 {
23 printf("exit_func2() is called.\n");
24 }
程序执行结果如下:
命令行参数,当执行一个程序时,调用exec的进程可将命令行参数传递给该新程序,进程间通信数据传输进程用到。写个程序输出其命令行参数,程序如下:
1 #include <stdio.h>
2 #include <stdlib.h>
3
4 int main(int argc,char *argv[])
5 {
6 int i;
7 for(i=0;i<argc;++i)
8 printf("argv[%d]: %s\n",i,argv[i]);
9 exit(0);
10 }
测试结果如下:
C程序的存储空间布局:
存储器分配函数:
#include <stdlib.h>
void *malloc(size_t size);
void *calloc(size_t nmemb,size_t size);
void *realloc(void *ptr, size_t size); //更改以前分配区的长度
void free(void *ptr);
写个程序练习函数的使用:
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4
5 int main()
6 {
7 int n;
8 int *pData;
9 printf("Enter the number: ");
10 scanf("%d",&n);
11 pData = (int*)malloc(sizeof(int)*n);
12 memset(pData,0,sizeof(int)*n);
13 printf("pData address is :%p\n",pData);
14 free(pData);
15 pData = (int*)calloc(n,sizeof(int));
16 printf("pData address is :%p\n",pData);
17 pData=realloc(pData,sizeof(int)*(n+10));
18 printf("pData address is :%p\n",pData);
19 free(pData);
20 exit(0);
21 }
环境变量:形式为name=value,环境变量可以在用进程进程间通信,exec函数可以通过环境变量进程传参数,例如在CGI程序中用到HTTP协议get和post方法对应的环境变量。环境变量可用于所有的子进程,这包括编辑器、脚本和应用。环境变量操作函数如下:
#include <stdlib.h>
char *getenv(const char *name); //指向与name关联的value的指针
int putenv(char *string); //取形式为name=value的字符串,将其放到环境表中
int setenv(const char *name, const char *value, int overwrite); //将name设置为value
int unsetenv(const char *name); //删除name的定义
int clearenv(void); //删除环境表中所有项
写个程序进行环境变量的读取设置及删除。程序如下:
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4
5 int main()
6 {
7 char *name;
8 char *value;
9 char *str = "LENGTH=10";
10 char *pvalue;
11 name = "QUERY";
12 value = "Hello,world";
13 //设置环境变量,1表示若那么存在,则先先删除
14 setenv(name,value,1);
15 //用字符串设置环境变量
16 putenv(str);
17 //取环境变量的值
18 pvalue = getenv(name);
19 printf("%s=%s\n",name,pvalue);
20 pvalue = getenv("LENGTH");
21 printf("LENGTH=%s\n",pvalue);
22 unsetenv("LENGTH");
23 //取系统HOME环境变量的值
24 pvalue = getenv("HOME");
25 printf("HOME=%s\N",pvalue);
26 exit(0);
27 }
程序执行结果如下:
全局跳转函数setjmp和longjmp:解决跨越函数跳跃,处理发生在深层次嵌套函数调用中出错情况非常有用。全局或者静态变量的值在执行longjmp是保持不变。函数原型如下:
int clearenv(void);
#include <setjmp.h>
int setjmp(jmp_buf env); //返回值为0为直接调用,从longjmp调用返回非0值
int sigsetjmp(sigjmp_buf env, int savesigs);
一般用法是:设置一个全局的jmp_buf变量,在主进程中调用setjmp()设置跳转变量,如果后面的函数出现错误,调用longjmp设置一个值,说明函数调用出错。写个程序来表达用法,程序如下:
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <setjmp.h>
5
6 void func1();
7 void func2();
8 void func3();
9 //定义一个全局的跳转变量
10 jmp_buf jmpbuffer;
11
12 int main()
13 {
14 int ret;
15 //获取返回值,0为直接调用
16 ret=setjmp(jmpbuffer);
17 switch(ret)
18 {
19 case 1:
20 printf("func1 is error.\n");
21 exit(-1);
22 case 2:
23 printf("func2 is error.\n");
24 exit(-1);
25 case 3:
26 printf("func3 is error.\n");
27 exit(-1);
28 }
29 func1();
30 exit(0);
31 }
32 void func1()
33 {
34 //longjmp(jmpbuffer,1);
35 func2();
36 }
37 void func2()
38 {
39 //longjmp(jmpbuffer,2);
40 func3();
41 }
42 void func3()
43 {
44 //设置跳转
45 longjmp(jmpbuffer,3);
46 }
程序执行结果如下:
进程资源限制函数:getrlimit和setrlimit,资源结果和函数原型如下:
struct rlimit {
rlim_t rlim_cur; /* Soft limit */
rlim_t rlim_max; /* Hard limit (ceiling for rlim_cur) */
};
#include <sys/resource.h>
int getrlimit(int resource, struct rlimit *rlim);
int setrlimit(int resource, const struct rlimit *rlim);
关于进程资源限制目前还不知道有何用,以后再来补充。
Unix环境高级编程(五)进程环境的更多相关文章
- Unix环境高级编程——守护进程记录总结(从基础到实现)
一.概念及其特征 守护进程是系统中生存期较长的一种进程,常常在系统引导装入时启动,在系统关闭时终止,没有控制终端,在后台运行.守护进程脱离于终端是为了避免进程在执行过程中的信息在任何终端上显示并且进程 ...
- UNIX环境高级编程--9. 进程控制
进程关系 当子进程终止时,父进程得到通知并能取得子进程的退出状态. 终端登录: 早起UNIX系统通过哑终端登录,本地的终端 or 远程的终端 .主机上链接的终端设备是固定的,所以同时登录数 ...
- Unix环境高级编程(六)进程控制
本章介绍Unix的进程控制,包括进程创建,执行程序和进程终止,进程的属性,exec函数系列,system函数,进程会计机制. 1.进程标识符 每一个进程都有一个非负整数标识的唯一进程ID.ID为0表示 ...
- UNIX环境高级编程--8. 进程控制
进程控制进程标识: 每一个进程都有一个非负整型表示的唯一进程ID.虽然唯一,但是ID可以复用.当一个进程结束后,其进程ID会被延迟复用. ID=0的进程通常是调度进程,常被称作交换进程(s ...
- UNIX环境高级编程——Linux进程地址空间和虚拟内存
一.虚拟内存 分段机制:即分成代码段,数据段,堆栈段.每个内存段都与一个特权级相关联,即0~3,0具有最高特权级(内核),3则是最低特权级(用户),每当程序试图访问(权限又分为可读.可写和可执行)一个 ...
- Unix环境高级编程(八)进程关系
本章看后给人似懂非懂的感觉,主要是不知道实际当中如何去使用.通过前面几章的学习,每个进程都有一个父进程,当子进程终止时,父进程得到通知并取得子进程的退出状态.先将本章基本的知识点总结如下,日后再看时候 ...
- UNIX环境高级编程——守护进程列表
amd:自动安装NFS(网络文件系统)守侯进程apmd:高级电源治理Arpwatch:记录日志并构建一个在LAN接口上看到的以太网地址和ip地址对数据库Autofs:自动安装治理进程automount ...
- UNIX环境高级编程——守护进程
一.守护进程简介 守护进程,也就是通常说的Daemon进程,是Linux中的后台服务进程.它是一个生存期较长的进程,通常独立于控制终端并且周期性地执行某种任务或等待处理某些发生的事件.守护进程常常在系 ...
- 《UNIX环境高级编程》笔记--环境变量
ISO C定义了一个函数getenv,可以用其取环境变量值. #include <stdlib.h> char* getenv(const char* name); //返回与name关联 ...
随机推荐
- C#中HTML和UBB互相转换的代码
C#中HTML和UBB互相转换的代码html转UBB的还不是很完美,有空修改,一些代码来自百度谷歌 private string DoHtmlToUBB(string _Html) { ...
- A12_ListView & ExpandablelistView
一.ListView 效果: 1.activity_main.xml <LinearLayout xmlns:android="http://schemas.android.com/a ...
- 给 TextBlock 加 ToolTip
<TextBlock ToolTip="{Binding RelativeSource={RelativeSource Self},Path=Text}" Text=&quo ...
- WebClient.DownloadData突然失灵
有如下的代码: try { byte[] acsMetadata; using (WebClient webClient = new WebClient()) { acsMetadata = we ...
- easyui datagrid种编辑器combobox选择的值不显示解决方案
var combobox_json = [{ "combobox_value" : "GDLB01", "combobox_name" : ...
- procedure
create or replace procedure get_username as begin v_id in number:=1 select * from uc_t_staff t where ...
- Discuz常见小问题-网站如何备份和恢复
进入后台之后,点击UCenter,然后在左侧的数据备份中点击提交,大概一两分钟会显示备份完成 备份好的数据在uc_server的data/backup文件夹中(文件名为时间+随机字符,里面就一个数据库 ...
- Android 之布局(一)
Android的布局类型: 主要有:LinearLayout(线性布局).RelativeLayout(相对布局).TableLayout(表格布局).AbsoluteLayout(绝对布局).Fra ...
- Activex打包于发布完整版---ActiveX打包
前面介绍了数字证书的原理与制作:http://blog.csdn.net/jiangtongcn/article/details/13508365,下面来看一下ActiveX组件的打包. 我现在有一个 ...
- GCD多线程使用
- (void)showTaped { /* dispatch_get_global_queue dispatch_get_main_queue dispatch_queue_create dispa ...