main函数
进程的执行是从main函数开始的,下面介绍一下main函数的原型。
int main(int argc,char *argv[])
可以看到main函数是有两个参数的,这两个参数可以从终端进行传递,第一参数表示传入参数的个数,第二个参数表示传入的参数,存入这个数组里。
进程的终止
进程终止的方式有八种,五种为正常终止
- 从main函数返回
- 调用exit函数
- 调用_exit或-Exit函数
- 最后一个例程从其启动例程中返回
- 从最后一个线程调用pthread_exit函数
异常终止的三种方式 - 调用abort函数
- 接到一个信号
- 最后一个线程对取消做出响应
终止进程的函数
atexit函数
这个函数用来操作进程终止时应该处理的函数,使用这个函数来进行记录进程终止时应该自动处理那些操作。
#include<stdlib.h>
int atexit(void (*func)(void));
这个函数以一个函数为参数。记录进程终止时执行什么操作,成为终止处理程序。
#include<stdlib.h>
void exit(int status)
void _Exit(int status)
#include<unistd.h>
void _exit(int status)
其中exit函数并不是直接进入内核,而是先清理打开的标准文件流,再进入内核。另外两个函数是直接进入内核,这三个函数都有一个参数表示返回的状态,系统通常有一个进程终止状态检查的操作。
#include<stdlib.h>
#include<stdio.h>
#include<unistd.h>
void func1()
{
printf("this is frist\n");
}
void func2()
{
printf("this is second\n");
}
int main()
{
atexit(func1);
atexit(func2);
}
结果:
root@ubuntu:/home/sun/project# ./test
this is second
this is frist
可以看到函数执行的顺序和记录终止操作是相反的。
环境表
每个程序都会接受到一个环境表,是用一个全局变量表示的。
extern char *environ;
![](https://img.haomeiwen.com/i16246589/3d5264db76a75f58.png)
可以看到这个环境表最后一个是NULL,在遍历环境表时可以使用NULL作为判断条件。
遍历所有环境表的一个程序
#include<stdlib.h>
#include<stdio.h>
#include<unistd.h>
int main()
{
extern char **environ;
int i=0;
while(*(environ+i)!=NULL)
{
printf("%s\n",*(environ+i));
++i;
}
}
结果:
root@ubuntu:/home/sun/project# ./test
LC_PAPER=zh_CN.UTF-8
XDG_VTNR=7
XDG_SESSION_ID=c2
LC_ADDRESS=zh_CN.UTF-8
CLUTTER_IM_MODULE=xim
LC_MONETARY=zh_CN.UTF-8
XDG_GREETER_DATA_DIR=/var/lib/lightdm-data/sun
SESSION=ubuntu
GPG_AGENT_INFO=/home/sun/.gnupg/S.gpg-agent:0:1
SHELL=/bin/bash
XDG_MENU_PREFIX=gnome-
VTE_VERSION=4205
TERM=xterm-256color
ROS_ROOT=/opt/ros/kinetic/share/ros
ROS_PACKAGE_PATH=/opt/ros/kinetic/share
QT_LINUX_ACCESSIBILITY_ALWAYS_ON=1
ROS_MASTER_URI=http://localhost:11311
LC_NUMERIC=zh_CN.UTF-8
WINDOWID=54525962
OLDPWD=/home/sun
GNOME_KEYRING_CONTROL=
UPSTART_SESSION=unix:abstract=/com/ubuntu/upstart-session/1000/1369
ROS_VERSION=1
GTK_MODULES=gail:atk-bridge:unity-gtk-module
USER=root
LD_LIBRARY_PATH=/opt/ros/kinetic/lib:/opt/ros/kinetic/lib/x86_64-linux-gnu
LC_TELEPHONE=zh_CN.UTF-8
QT_ACCESSIBILITY=1
环境变量
常见的环境变量
- HOME表示home的起始目录
- LOGNAME登录名
- PATH搜索可执行文件的路径
- PWD当前工作目录的绝对路径
- SHELL用户首先得shell名
操作环境变量的方法
#include<stdlib.h>
char *getenv(const char *name);
#include<stdlib.h>
#include<stdio.h>
#include<unistd.h>
int main()
{
char *p=getenv("PATH");
printf("%s\n",p);
}
结果:
root@ubuntu:/home/sun/project# ./test
/opt/ros/kinetic/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games
通过环境变量的名字来得到环境变量,返回一个字符指针。
#include<stdlib.h>
int putenv(char *str);
int setenv(const char *name,const char *value,int rewrite);
int unsetenv(const char *name);
- putenv函数以name=value的形式将环境变量添加到环境表中,如果已经存在会清除原先的在将值写入。
- setenv函数表示将name设置为value,如果name已经存在并且rewrite不为0,那么将新的值写入,如果rewrite为0,则不变。
- unsetenv函数表示将name的值进行清除,如果name不存在也不会报错
需要注意的是putenv函数是将这个str的地址直接引用到环境变量表中的,因此如果在栈中使用局部变量在这个函数中设置,当这个栈被释放后便会出错。
#include<stdlib.h>
#include<stdio.h>
#include<unistd.h>
int main()
{
putenv("AA=ADJSK");
char *p=getenv("AA");
printf("%s\n",p);
unsetenv("AA");
}
结果:
root@ubuntu:/home/sun/project# ./test
ADJSK
setjmp和longjmp函数
这两个函数和goto类似都是当执行到某句代码是,返回到某个位置,但是goto函数不能跨越函数,因此这两个函数便是用来当执行到某个函数时,符合一定的条件时返回到另一个函数。
网友评论