【unix】进程环境、进程控制

进程

进程环境

进程终止
环境表
C存储空间布局

atexit

atexit函数是一个特殊的函数,它是在正常程序退出时调用的函数,我们把他叫为登记函数
个进程可以登记若⼲个个函数,这些函数由exit⾃动调⽤,这些函数被称为终⽌处理函数, atexit函数可以登记这些函数。 exit调⽤终⽌处理函数的顺序和atexit登记的顺序相反

#include<stdlib.h>
int atexit(void (*func)(void));

传入的参数是一个函数地址,调用此参数时无需向它传递任何参数,也不期望它返回任何一个值

getenv

获取环境变量的值

#include <stdlib.h>

char *getenv(const char *name);

函数返回一个指针,它指向name=value字符串中的value,若未找到返回NULL

putenv setenv unsetenv

putenv取形式为name=value的字符串,将其放到环境表中。如果name已经存在,则先删除原来的定义(添加或者修改 环境变量)。
setenv将name设置为value,overwrite参数指示是否覆盖已存在的同名变量。如果overwrite参数为0,且已存在同名变量,则不会修改该变量;否则,将会覆盖原有的同名变量
unsetenv删除name的定义,即使name不存在也不算出错

#include <stdlib.h>
//str:指向环境变量的指针,其中环境变量必须以 "name=value" 的形式给出
int putenv(char *str);
//成功返回0,出错返回非0

int setenv(const char *name, const char *value, int overwrite);
int unsetenv(const char *name);
//成功返回0,出错返回非-1

setjmp longjmp

可跨函数的goto
setjmp函数用于记录当前位置,初次调用他的值等于0.然后再调用longjmp函数,此时longjmp会跳转到setjmp函数的地方,使得setjmp函数的返回值为非0的val值

int setjmp(jmp_buf buf);
void longjmp(jmp_buf buf,int val);

例子:

#include<stdio.h>
#include<setjmp.h>

jmp_buf buf;

void hello(){
    printf("hello\n");
    longjmp(buf,1);
    printf("you will see this\n");
} 

main(){
    if(setjmp(buf)==0){
        printf("first \n");
        hello();
    }else
        printf("ok\n");
    return 0;
}

getrlimit setlimit

每个进程都有一组资源限制,可用getrlimit获取和setlimit更改

#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; //软限制 :当前的限制
  rlim_t rlim_max; //硬限制 :软限制的最大值
};

resource:可能的选择有
RLIMIT_AS //进程的最大虚内存空间,字节为单位。
RLIMIT_CORE //内核转存文件的最大长度。
RLIMIT_CPU //最大允许的CPU使用时间,秒为单位。当进程达到软限制,内核将给其发送SIGXCPU信号,这一信号的默认行为是终止进程的执行。然而,可以捕捉信号,处理句柄可将控制返回给主程序。如果进程继续耗费CPU时间,核心会以每秒一次的频率给其发送SIGXCPU信号,直到达到硬限制,那时将给进程发送 SIGKILL信号终止其执行。
RLIMIT_DATA //进程数据段的最大值。
RLIMIT_FSIZE //进程可建立的文件的最大长度。如果进程试图超出这一限制时,核心会给其发送SIGXFSZ信号,默认情况下将终止进程的执行。
RLIMIT_LOCKS //进程可建立的锁和租赁的最大值。
RLIMIT_MEMLOCK //进程可锁定在内存中的最大数据量,字节为单位。
RLIMIT_MSGQUEUE //进程可为POSIX消息队列分配的最大字节数。
RLIMIT_NICE //进程可通过setpriority() 或 nice()调用设置的最大完美值。
RLIMIT_NOFILE //指定比进程可打开的最大文件描述词大一的值,超出此值,将会产生EMFILE错误。
RLIMIT_NPROC //用户可拥有的最大进程数。
RLIMIT_RTPRIO //进程可通过sched_setscheduler 和 sched_setparam设置的最大实时优先级。
RLIMIT_SIGPENDING //用户可拥有的最大挂起信号数。
RLIMIT_STACK //最大的进程堆栈,以字节为单位。

成功执行时,返回0。失败返回-1

进程控制

每个进程都有一个非负整数表示的唯一进程ID---(pid)
用户ID---(uid)
组ID---(gid)
解释器文件

getpid

#include <unistd.h>

pid_t getpid(void); //return 调用进程的进程ID
pid_t getppid(void);//return 调用进程的父进程ID
pid_t getuid(void);//return 调用进程的实际用户ID
pid_t geteuid(void);//return 调用进程的有效用户ID
pid_t getgid(void);//return 调用进程的实际组ID
pid_t getegid(void);//return 调用进程的有效组ID

fork

创建子进程

pid_t fork (void);
pid_t vfork (void); //vfork可保证子进程先运行,在它调用exec或exit后父进程才继续运行

调用它一次返回两次,在调用进程(父进程)中返回一次,返回值是派生进程的进程ID号
fork的一个特性是父进程所有打开的文件描述符都被复制到子进程中,就好像执行了dup函数
在子进程中返回一次,返回值为0

wait waitpid

回收子进程的资源

pid_t wait(int *statloc);
pid_t waitpid(pid_t pid , int *statloc ,int options);

statloc : 通过statloc指针返回子进程的终止状态 , pid : 指定想等待的进程id(值-1表示等待第一个终止的子进程) , optinos : 指定附加选项(WNOHANG 表示告知内核在没有已终止的子进程时不要阻塞)
输出 成功为已终止子进程id , 出错则为-1

exec

调用进程
存放在硬盘上的可执行文件能够被UNIX执行的唯一方法是: 由一个现有进程调用六个exec函数的某一个

#include <unistd.h>
 
int execl( const char *pathname, const char *arg0, ... /* (char *)0 */ );
 
int execv( const char *pathname, char *const argv[] );
 
int execle( const char *pathname, const char *arg0, ... /* (char *)0, char *const envp[] */ );
 
int execve( const char *pathname, char *const argv[], char *const envp[] );
 
int execlp( const char *filename, const char *arg0, ... /* (char *)0 */ );
 
int execvp( const char *filename, char *const argv[] );
 
6个函数返回值:若出错则返回-1,若成功则不返回值

参数:要执行的程序路径,参数

char *const ps_argv[] ={"ps", "-o", "pid,ppid,pgrp,session,tpgid,comm", NULL};
 
char *const ps_envp[] ={"PATH=/bin:/usr/bin", "TERM=console", NULL};
 
execl("/bin/ps", "ps", "-o", "pid,ppid,pgrp,session,tpgid,comm", NULL);
 
execv("/bin/ps", ps_argv);
 
execle("/bin/ps", "ps", "-o", "pid,ppid,pgrp,session,tpgid,comm", NULL, ps_envp);
 
execve("/bin/ps", ps_argv, ps_envp);
 
execlp("ps", "ps", "-o", "pid,ppid,pgrp,session,tpgid,comm", NULL);
 
execvp("ps", ps_argv);

setuid

设置实际用户ID和有效用户ID

#include <unistd.h>
int setuid(uid_t uid);

当root 使用setuid来变换成其他用户识别码时, root 权限会被抛弃, 完全转换成该用户身份, 也就是说, 该进程往后将不再具有可setuid()的权利, 如果只是向暂时抛弃root 权限, 稍后想重新取回权限, 则必须使用seteuid

seteuid

只更改有效用户ID

#include <unistd.h>
int seteuid(uid_t ruid , uid_t euid);

system

执行shell命令

int system(const char * command)

getlogin

获取用户登录名

char *getlogin(void);

times

获取时间

#include <sys/times.h>
clock_t times(struct tms *buf);

/* Structure describing CPU time used by a process and its children.  */ 
struct tms 
{ 
    clock_t tms_utime ;          /* User CPU time.  用户程序 CPU 时间*/ 
    clock_t tms_stime ;          /* System CPU time. 系统调用所耗费的 CPU 时间 */ 

    clock_t tms_cutime ;         /* User CPU time of dead children. 已死掉子进程的 CPU 时间*/ 
    clock_t tms_cstime ;         /* System CPU time of dead children.  已死掉子进程所耗费的系统调用 CPU 时间*/ 
};

成功返回墙上时钟时间,失败返回-1

进程调度

调度策略和调度优先级是由内核决定的。进程可以调整nice值选择以更低优先级运行(nice值越小,优先级越高)
nice

获取或更改它的nice值

int nice(int incr);

参数incr被增加到调用进程的nice值上!成功设置输出inc的值,错误返回-1

getpriority

获取进程、进程组和用户的进程执行优先级

int getpriority(int which, int who);

参数 which的不同时who代表的意思也不一样 :
PRIO_PROCESS    who为进程的ID
PRIO_PGRP       who为进程组ID
PRIO_USER       who为用户ID
setpriority

设置进程的优先级

int setpriority(int which, int who, int prio);

参数 which的不同时who代表的意思也不一样 :
PRIO_PROCESS    who为进程的ID
PRIO_PGRP       who为进程组ID
PRIO_USER       who为用户ID

进程关系、信号

alarm

1.alarm函数的作用是设置一个定时器,在seconds秒之后,将会发送SIGALRM信号给当前的进程,故而alarm函数也被称为闹钟函数。
如果不对SIGALRM信号进行忽略或者捕捉,默认情况下会退出进程。

2.如果second的值为0的话,那么定时器将会被取消。

3.如果在seconds秒内再次调用了alarm函数设置了新的闹钟,那么之前设置的秒数将会被新的闹钟时间所取代。

unsigned int alarm(unsigned int seconds)

1.如果seconds的值被设置为0,那么返回值将会是0
2.如果在当前的定时器之前设置过定时器,那么当前定时器返回的值将是之前定时器剩余的秒数

守护进程

syslog

syslogd守护进程用于解决守护进程的日志记录问题,而日志信息保存的位置和记录的信息级别是在syslogd守护进程的配置文件中设定的
Openlog函数用于打开系统日志服务的一个连接;
Syslog函数用于向日志文件中写入消息,在这里可以规定消息的优先级、消息的输出格式等;
Closelog函数用于关闭系统日志服务的连接。
调用openlog是可选择的。如果不调用openlog,则在第一次调用syslog时,自动调用openlog。调用closelog也是可选择的,它 只是关闭被用于与syslog守护进程通信的描述符

void syslog(int priority, const char *format, ...);

使用实例

int main(int argc, char **argv) 
{ 
    syslog(LOG_ERR|LOG_USER,"test - %m/n"); 
    openlog("SyslogTest", LOG_CONS | LOG_PID, 0); 
    syslog(LOG_DEBUG,"This is a syslog test message generated by program '%s'/n",argv[0]); 
    closelog(); 
    return 0; 
}

daemon_init daemon_inted

daemon_init函数能把一个普通进程转变为守护进程
daemon_inted函数能把一个普通进程转变为inted守护进程

int daemon_init(const char *pname , int facility);
int daemon_inted(const char *pname , int facility);
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值