环境变量
KEY=VALUE
查看环境变量:export
环境变量:environ,定义为一个char**,是一个字符指针数组的起始位置。
环境变量的存放,类似argv的存放
例子:
#include <stdio.h>
#include <stdlib.h>
extern char **environ;
int main()
{
int i=0;
for(i=0;environ[i]!=NULL;i++)
puts(environ[i]);
exit(0);
}
运行就可以看到环境变量
相关函数:
getenv();
----------------------- get an environment variable
#include <stdlib.h>
char *getenv(const char *name);
例子:
#include <stdio.h>
#include <stdlib.h>
int main()
{
puts(getenv("PATH"));
exit(0);
}
运行后就可以得到PATH值:
setenv();
--------------change or add an environment variable
#include <stdlib.h>
int setenv(const char *name, const char *value, int overwrite);
第一个参数:环境变量的名字,存在就是改变,不存在就是增加
第三个参数:是否覆盖,如果是真则用现在的覆盖以前的,如果是假,则新的不会生效
putenv();
---------------------- change or add an environment variable
#include <stdlib.h>
int putenv(char *string);//不好用
C程序的存储空空间布局
相关命令pmap:
让代码停在getchar处:
#include <stdio.h>
#include <stdlib.h>
int main()
{
puts(getenv("PATH"));
getchar();
exit(0);
}
ps axf//查看进程关系
pmap 2997查看地址空间的分布
库
动态库
静态库
手工装载库:开机启动的时候
相关函数:
dlopen
dlclose
------------------------open and close a shared object
dlerror
------------------------ obtain error diagnostic for functions in the dlopen API
dlsym
--------------------obtain address of a symbol in a shared object or executable
#include <dlfcn.h>
void *dlopen(const char *filename, int flags);
int dlclose(void *handle);
char *dlerror(void);
void *dlsym(void *handle, const char *symbol);
注意:Link with -ldl.
例子(man手册中的例子,可自行查看):
#include <stdio.h>
#include <stdlib.h>
#include <dlfcn.h>
#include <gnu/lib-names.h> /* Defines LIBM_SO (which will be a
string such as "libm.so.6") */
int
main(void)
{
void *handle;
double (*cosine)(double);
char *error;
handle = dlopen(LIBM_SO, RTLD_LAZY);
if (!handle) {
fprintf(stderr, "%s\n", dlerror());
exit(EXIT_FAILURE);
}
dlerror(); /* Clear any existing error */
cosine = (double (*)(double)) dlsym(handle, "cos");
/* According to the ISO C standard, casting between function
pointers and 'void *', as done above, produces undefined results.
POSIX.1-2003 and POSIX.1-2008 accepted this state of affairs and
proposed the following workaround:
*(void **) (&cosine) = dlsym(handle, "cos");
This (clumsy) cast conforms with the ISO C standard and will
avoid any compiler warnings.
The 2013 Technical Corrigendum to POSIX.1-2008 (a.k.a.
POSIX.1-2013) improved matters by requiring that conforming
implementations support casting 'void *' to a function pointer.
Nevertheless, some compilers (e.g., gcc with the '-pedantic'
option) may complain about the cast used in this program. */
error = dlerror();
if (error != NULL) {
fprintf(stderr, "%s\n", error);
exit(EXIT_FAILURE);
}
printf("%f\n", (*cosine)(2.0));
dlclose(handle);
exit(EXIT_SUCCESS);
}
函数跳转
例子:
#include <stdio.h>
#include <stdlib.h>
static void d(void)
{
printf("%s():begin.\n",__FUNCTION__);
printf("%s():End.\n",__FUNCTION__);
}
static void c(void)
{
printf("%s():begin.\n",__FUNCTION__);
printf("%s():Call d().\n",__FUNCTION__);
d();
printf("%s():d() returned.\n",__FUNCTION__);
printf("%s():End.\n",__FUNCTION__);
}
static void b(void)
{
printf("%s():begin.\n",__FUNCTION__);
printf("%s():Call c().\n",__FUNCTION__);
c();
printf("%s():c() returned.\n",__FUNCTION__);
printf("%s():End.\n",__FUNCTION__);
}
static void a(void)
{
printf("%s():begin.\n",__FUNCTION__);
printf("%s():Call a().\n",__FUNCTION__);
b();
printf("%s():a() returned.\n",__FUNCTION__);
printf("%s():End.\n",__FUNCTION__);
}
int main()
{
printf("%s():begin.\n",__FUNCTION__);
printf("%s():Call a().\n",__FUNCTION__);
a();
printf("%s():a() returned.\n",__FUNCTION__);
printf("%s():End.\n",__FUNCTION__);
exit(0);
}
运行结果:
可以看到压栈和弹栈的过程
setjmp()//设置跳转点
---------------------save stack context for nonlocal goto
#include <setjmp.h>
int setjmp(jmp_buf env);
返回值:执行一次返回两次,如果是设置跳转点,那么返回值就是0,如果是从别的地方跳转回来,那么返回值就是非0值
setjmp() and sigsetjmp() return 0 if returning directly, and nonzero
when returning from longjmp(3) or siglongjmp(3) using the saved context.
longjmp()//往回跳
--------------------- nonlocal jump to a saved stack context
#include <setjmp.h>
void longjmp(jmp_buf env, int val);
以上两个函数可以实现跨函数跳转
例子:
#include <stdio.h>
#include <stdlib.h>
#include <setjmp.h>
static jmp_buf save;
static void d(void)
{
printf("%s():begin.\n",__FUNCTION__);
printf("%s():Jump now!\n",__FUNCTION__);
longjmp(save,6);
printf("%s():End.\n",__FUNCTION__);
}
static void c(void)
{
printf("%s():begin.\n",__FUNCTION__);
printf("%s():Call d().\n",__FUNCTION__);
d();
printf("%s():d() returned.\n",__FUNCTION__);
printf("%s():End.\n",__FUNCTION__);
}
static void b(void)
{
printf("%s():begin.\n",__FUNCTION__);
printf("%s():Call c().\n",__FUNCTION__);
c();
printf("%s():c() returned.\n",__FUNCTION__);
printf("%s():End.\n",__FUNCTION__);
}
static void a(void)
{
int ret;
printf("%s():begin.\n",__FUNCTION__);
ret=setjmp(save);
if(ret==0)
{
printf("%s():Call a().\n",__FUNCTION__);
b();
printf("%s():a() returned.\n",__FUNCTION__);
}
else
{
printf("%s():Iumped back here with code %d\n",__FUNCTION__,ret);
}
printf("%s():End.\n",__FUNCTION__);
}
int main()
{
printf("%s():begin.\n",__FUNCTION__);
printf("%s():Call a().\n",__FUNCTION__);
a();
printf("%s():a() returned.\n",__FUNCTION__);
printf("%s():End.\n",__FUNCTION__);
exit(0);
}
运行结果:
资源的获取以及控制
getrlimit();//获取资源总量
setrlimit();//设置资源总量
#include <sys/time.h>
#include <sys/resource.h>
int getrlimit(int resource, struct rlimit *rlim);
int setrlimit(int resource, const struct rlimit *rlim);
struct rlimit {
rlim_t rlim_cur; /* Soft limit */
rlim_t rlim_max; /* Hard limit (ceiling for rlim_cur) */
};
root用户和普通用户使用这个函数的权限是不一样的
通用的规则:软限制可以升高可以降低,但是即使升高也不能超过硬限制
普通用户对于硬限制只可以降低不可以升高,对于软限制可以提高和降低
root用户对于硬限制可以升高也可以降低,对于软限制可以升高也可以降低
利用这两个函数可以封装ulimit命令