博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Unix环境高级编程(五)进程环境
阅读量:6675 次
发布时间:2019-06-25

本文共 4697 字,大约阅读时间需要 15 分钟。

  本章主要介绍了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 <>

int atexit(void (*function)(void));  //成功返回0,否则返回非0值

一个C程序启动和终止的过程如下图所示:

 

内核使程序执行的唯一方法是调用一个exec函数,终止的唯一方法是显式或者隐式地通过exit函数调用_exit()或_Exit(),也可以非自愿的由一个信号使其终止。

写个程序进程练习,程序如下:

1 #include 
2 #include
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 
2 #include
3 4 int main(int argc,char *argv[]) 5 { 6 int i; 7 for(i=0;i

测试结果如下:

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 
2 #include
3 #include
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 
2 #include
3 #include
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 
2 #include
3 #include
4 #include
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);

关于进程资源限制目前还不知道有何用,以后再来补充。

转载于:https://www.cnblogs.com/alantu2018/p/8465979.html

你可能感兴趣的文章
网络学习笔记2
查看>>
JPA--多对多关系
查看>>
配置sharepoint 2010错误:Microsoft.SharePoint.Upgrad...
查看>>
Windows04.CMap
查看>>
UUID 生成算法JS版
查看>>
JAVA中,Map转实体类、实体类转Map的方法
查看>>
判断dubbo接口是否正常
查看>>
100-19
查看>>
获取n!的末尾有多少个0?
查看>>
设计模式之工厂模式
查看>>
度量平台角色的含义及运用
查看>>
前嗅ForeSpider教程:创建模板
查看>>
JAVA 排序 冒泡法
查看>>
Nginx安装和常用配置文档
查看>>
oracle数据库控制文件Control files
查看>>
docker常用网络模型:
查看>>
zTree模糊查询节点并且隐藏节点
查看>>
K3CLOUD自动备份Oracle数据库并删除指定天数前的备份
查看>>
java mail 签名 加密
查看>>
shell训练day15
查看>>