进程id:系统中每一个进程有惟一的id,在c语言中用pid_t类型表示,是个非负整数。linux
进程状态:就绪,运行,挂起,中止等状态c++
描述虚拟地址空间的信息shell
描述控制终端的信息bash
进程执行时的当前工做目录(current working directory)微信
umask掩码session
文件描述符表,包含不少指向file结构体的指针函数
和信号相关的信息学习
用户id和组id编码
会话(session)和进程组spa
进程可使用的资源上限(Resource Limit)
用【ulimit -a】查看:
ys@ys:~$ ulimit -a core file size (blocks, -c) 0 data seg size (kbytes, -d) unlimited scheduling priority (-e) 0 file size (blocks, -f) unlimited pending signals (-i) 7743 max locked memory (kbytes, -l) 16384 max memory size (kbytes, -m) unlimited open files (-n) 1024 pipe size (512 bytes, -p) 8 POSIX message queues (bytes, -q) 819200 real-time priority (-r) 0 stack size (kbytes, -s) 8192 cpu time (seconds, -t) unlimited max user processes (-u) 7743 virtual memory (kbytes, -v) unlimited file locks (-x) unlimited
查看全部的环境变量:env
环境写法:等号先后没有空格
KEY=VALUE
经常使用的环境变量:
获取环境变量:getenv
#include <stdlib.h> char *getenv(const char *name);
返回值:
成功:返回指针
失败:返回NULL
设置环境变量:setenv
#include <stdlib.h> int setenv(const char *name, const char *value, int overwrite);
删除环境变量:unsetenv
#include <stdlib.h> int unsetenv(const char *name);
设置环境变量和删除环境变量通常不用系统函数,而是编辑【~/.bashrc】文件。
使用【exprot key=value】。
建立进程:fork
#include <sys/types.h> #include <unistd.h> pid_t fork(void);
得到当前进程本身id:getpid
得到当前进程的父进程的id:getppid
ss #include <unistd.h> pid_t getpid(void); pid_t getppid(void);
理解fork的小例子:
#include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <unistd.h> int main(){ //char* val = getenv("HOME"); printf("begin...\n"); pid_t pid = fork(); printf("end...\n"); }
执行结果:
ys@ys:~/test$ ./en begin... end... ys@ys:~/test$ end...
从执行结果发下:
1,【begin】被打印出1次;【end】被打印出2次。
2,第二个【end】跑到了shell的后面。
分析:
下面的例子能够了解,getpid和getppid的用法:
#include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <unistd.h> int main(){ //char* val = getenv("HOME"); printf("begin...\n"); pid_t pid = fork(); //child process if(pid == 0){ printf("child: pid=%d, ppid=%d\n", getpid(), getppid()); } //parent proces else if(pid > 0){ printf("parent: pid=%d, child id:%d\n", getpid(), pid); sleep(1);//为了让子进程先结束 } printf("end...\n"); }
查看进程的命名:ps
ys@ys:~$ ps aux USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND root 1 0.0 0.3 159928 7536 ? Ss 13:53 0:02 /sbin/init spla root 2 0.0 0.0 0 0 ? S 13:53 0:00 [kthreadd] ys 4029 0.0 0.0 4508 812 pts/0 S+ 16:30 0:00 ./en ys 4030 0.0 0.0 4508 80 pts/0 S+ 16:30 0:00 ./en ys 4043 0.1 0.2 29560 4936 pts/1 Ss 16:30 0:00 bash ys 4051 0.0 0.1 44472 3700 pts/1 R+ 16:30 0:00 ps aux
从下图能够看出子进程4030的父进程是4029,父进程4029的父进程是1671,进程1671是bash(shell)程序。因此的进程都是从进程1:【/sbin/init splash】衍生出来的。
ys@ys:~$ ps ajx PPID PID PGID SID TTY TPGID STAT UID TIME COMMAND 0 1 1 1 ? -1 Ss 0 0:02 /sbin/init splash 1661 1671 1671 1671 pts/0 4029 Ss 1000 0:00 bash 1671 4029 4029 1671 pts/0 4029 S+ 1000 0:00 ./en 4029 4030 4029 1671 pts/0 4029 S+ 1000 0:00 ./en 1661 4043 4043 4043 pts/1 4055 Ss 1000 0:00 bash 4043 4055 4055 4043 pts/1 4055 R+ 1000 0:00 ps ajx
给进程发送信号:kill
使用【kill -l】查看信号列表,发现9号信号就杀死进程的信号。
ys@ys:~$ kill -l 1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL 5) SIGTRAP 6) SIGABRT 7) SIGBUS 8) SIGFPE 9) SIGKILL 10) SIGUSR1 11) SIGSEGV 12) SIGUSR2 13) SIGPIPE 14) SIGALRM 15) SIGTERM 16) SIGSTKFLT 17) SIGCHLD 18) SIGCONT 19) SIGSTOP 20) SIGTSTP 21) SIGTTIN 22) SIGTTOU 23) SIGURG 24) SIGXCPU 25) SIGXFSZ 26) SIGVTALRM 27) SIGPROF 28) SIGWINCH 29) SIGIO 30) SIGPWR 31) SIGSYS 34) SIGRTMIN 35) SIGRTMIN+1 36) SIGRTMIN+2 37) SIGRTMIN+3 38) SIGRTMIN+4 39) SIGRTMIN+5 40) SIGRTMIN+6 41) SIGRTMIN+7 42) SIGRTMIN+8 43) SIGRTMIN+9 44) SIGRTMIN+10 45) SIGRTMIN+11 46) SIGRTMIN+12 47) SIGRTMIN+13 48) SIGRTMIN+14 49) SIGRTMIN+15 50) SIGRTMAX-14 51) SIGRTMAX-13 52) SIGRTMAX-12 53) SIGRTMAX-11 54) SIGRTMAX-10 55) SIGRTMAX-9 56) SIGRTMAX-8 57) SIGRTMAX-7 58) SIGRTMAX-6 59) SIGRTMAX-5 60) SIGRTMAX-4 61) SIGRTMAX-3 62) SIGRTMAX-2 63) SIGRTMAX-1 64) SIGRTMAX
由父进程建立5个子进程的例子:
#include <sys/types.h> #include <unistd.h> #include <stdio.h> int main(){ int i = 0; pid_t pid = 0; for(i = 0; i < 5; ++i){ pid = fork(); if(pid == 0){ //child process //printf("child: pid=%d, ppid=%d\n", getpid(), getppid()); break; } else if (pid > 0){ //parent process //printf("parent: pid=%d, ppid=%d\n", getpid(), getppid()); } } sleep(i); printf("proces:%d will die:pid=%d,ppid=%d\n", i,getpid(), getppid()); }
执行结果:
ys@ys:~/test$ ./fo proces:0 will die:pid=2139,ppid=2138 proces:1 will die:pid=2140,ppid=2138 proces:2 will die:pid=2141,ppid=2138 proces:3 will die:pid=2142,ppid=2138 proces:4 will die:pid=2143,ppid=2138 proces:5 will die:pid=2138,ppid=1704
要点在【break】和【sleep(i)】这2个地方。
不加break的话,子进程也会建立子进程。
观察【sleep(i);]这行,执行到这行的时间点,若是i=0,则说明是第一建立的子进程;
若是i=4,说明是最后建立的子进程,若是i=5,说明是父进程。因此根据i的值,进行sleep,就可以实现先建立的子进程先执行完,后建立的后执行完,最后才是父进程执行完。
在当进程调用别的程序:execl和execlp
#include <unistd.h> int execl(const char *path, const char *arg, .../* (char *) NULL */); int execlp(const char *file, const char *arg, .../* (char *) NULL */);
调用ls的例子:
#include <unistd.h> #include <stdio.h> int main(){ execl("/bin/ls", "ls", "-l", "--color=auto", NULL); perror("ls"); printf("not back\n"); }
孤儿进程和僵尸进程
孤儿进程:父进死了,被init进程领养,变成孤儿进程。
僵尸进程:子进程死了,但父进程没有回收子进程的资源(pcb(大结构体)),变成僵尸进程。
回收僵尸进程的方法:不能再用kill去杀,杀死父进程,让init领养,init负责回收。
查看僵尸进程:
PPID PID PGID SID TTY TPGID STAT UID TIME COMMAND 1704 2683 2683 1704 pts/0 2683 S+ 1000 0:00 ./zo 2683 2684 2683 1704 pts/0 2683 Z+ 1000 0:00 [zo] <defunct>
发现有【Z+】和《defunct》就是僵尸进程。
回收子进程:wait函数
#include <sys/types.h> #include <sys/wait.h> pid_t wait(int *wstatus);
做用:
wstatus:传出参数,里面有子进程死亡的缘由。
查看wstatus的方法:使用下面2组宏。
WIFEXITED(wstatus) WEXITSTATUS(wstatus) WIFSIGNALED(wstatus) WTERMSIG(wstatus)
正常死亡:WIFEXITED(wstatus)返回真,使用WEXITSTATUS(wstatus)获得退出状态。
退出状态的具体含义:return 后面的数字;或者exit 括号里的数字。
非正常死亡(被信号杀死):WIFSIGNALED(wstatus)返回真,使用WTERMSIG(wstatus)获得杀死它的信号(kill -l 显示出来的数字)。
返回值:
wait的例子:
#include <sys/types.h> #include <unistd.h> #include <stdio.h> #include <wait.h> #include <stdlib.h> int main(){ int i = 0; pid_t pid = 0; pid = fork(); if(pid == 0){ //child process while(1){ printf("child: pid=%d, ppid=%d\n", getpid(), getppid()); sleep(3); //return 101; //exit(111); //sleep(2); } } else if (pid > 0){ //parent process printf("parent: pid=%d, ppid=%d\n", getpid(), getppid()); int wstatus; pid_t pid = wait(&wstatus); if(WIFEXITED(wstatus)){ printf("child die pid=%d, status=%d\n",pid, WEXITSTATUS(wstatus)); } if(WIFSIGNALED(wstatus)){ printf("child die pid=%d, status=%d\n",pid, WTERMSIG(wstatus)); } } }
分析:
回收子进程:waitpid
#include <sys/types.h> #include <sys/wait.h> pid_t waitpid(pid_t pid, int *wstatus, int options);
<font color="green">
</font>