进程的基本概念
- 进程是LInux中管理事务的基本单元 代表资源的总合
进程的属性
进程号
/*获得该进程进程号*/
pid_t getpid();
/*获得该进程的父进程号*/
pid_t getppid();
用linux命令来获取进程号
ps -o <format>
ps -o pid
ps -ef /*查看所以进程*/
进程组:一个进程创建的所有子进程的集合是一个进程组
用户号
一个进程有两个用户号:UID和EUID,运行文件的那个用户是UID,文件拥有者的id是EUID有效uid。用户号主要作用是文件的安全性。
uid_t getuid(); 获取真实用户
uid_t geteuid(); 获取有效UID
gid_t getgid(); 获取真实进程组id
gid_t getegid(); 获取有效进程组id
int setuid(uid_t uid); 设置真实用户ID
int seteuid(uid_t uid); 设置有效用户ID
int setgid(gid_t); 设置真实组ID
int setugid(gid_t gid); 设置有效组ID
会话号
几个有关联的进程会组成一个会话组,这个会话组有一个会话号,这个会话组号是其中一个进程的pid
获取当前进程的会话组号
pid_t getsid(pid_t pid);
代码
#include <unistd.h>
#include <signal.h>
#include <fcntl.h>
#include <sys/syslog.h>
#include <sys/param.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <stdlib.h>
int main()
{
printf("this process pid is %d\n",getpid());
printf("this process uid is %d\n",getuid());
printf("this process euid is %d\n",geteuid());
printf("this process gid is %d\n",getgid());
printf("this process egid is %d\n",getgid());
/*获取 uid euid suid的函数*/
int uid, euid, suid;
uid = euid = suid = -1;
getresuid(&uid, &euid, &suid);
printf("uid=%d euid=%d suid=%d\n",uid,euid,suid);
return 0;
}
进程管理和控制
进程的创建
pid_t fork();
fork函数创建一个子进程并且返回两次,当返回值为-1说明创建子进程失败
如果返回值等于0说明当前进程是子进程
如果返回值大于0说明当前是父进程
#include <unistd.h>
#include <signal.h>
#include <fcntl.h>
#include <sys/syslog.h>
#include <sys/param.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char**argv)
{
pid_t pid;
pid = fork();
if( pid == 0)
{
printf("\nI am child pid is %d\n",getpid());
exit(0);
}
else if(pid>0)
{
printf("\nI am parent pid is %d\n",getpid());
}
else
{
printf("fork error\n");
exit(-1);
}
return 0;
}
创建的子进程将会复制父进程当中堆区,栈区,代码区,静态区的内存,但是不会
复制信号的设置函数。
进程的代码执行
当我们想要在进程当中执行其他程序,即替代当前进程
int execl(const char *path, const char *arg, ...);
int execlp(const char *file, const char *arg, ...);
会从$PATH环境变量中找到目录
int execle(const char *path, const char *arg,
..., char * const envp[]);
int execv(const char *path, char *const argv[]);
int execvp(const char *file, char *const argv[]);
int execve(const char *file, char *const argv[],
char *const envp[]);
exec函数一般不会返回,当返回-1时说明执行代码失败。
僵尸进程及其处理
子进程在结束后会退出,但是它的内存资源任然存在,只有当父进程读取确认子进程
的退出状态后才会释放子进程的资源,我们将子进程结束但是内存未释放这一个状
态称为僵尸状态。此时的进程无任何作用,也无法调度。
僵尸状态产生原因:1.父进程为确认读取子进程结束。2.父进程异常终止,子进程任在运行
- wait和waitpid函数
int wait(int *stat_loc);
int waitpid( pid_t pid, int *stat_loc, int options);
wait函数会阻塞等待任意一个结束的子进程惠祖设,waitpid等待指定某个子进程
结束,当pid为-1时和wait函数一样。
stat_loc表示子进程退出时候的状态,pid是指要等待的进程号,options指等待方式。
options:1.WNOHANG 若子进程未结束直接返回0不再等待。
2.WUNTRACCED 若该进程已经暂停则返回其状态。
进程的状态:
define TASK_RUNNING 0 还在运行当中
define TASK_INTERRUPTIBLE 1 可暂停
define TASK_UNINTERRUPTIBLE 2 不可暂停
define TASK_STOPPED 4 终止状态
define TASK_ZOMBIE 8 僵尸状态
代码
#include <unistd.h>
#include <signal.h>
#include <fcntl.h>
#include <sys/syslog.h>
#include <sys/param.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char**argv)
{
pid_t pid;
pid = fork();
if( pid == 0)
{
printf("\nI am child pid is %d\n",getpid());
exit(0);
}
else if(pid>0)
{
printf("\nI am parent pid is %d\n",getpid());
wait(NULL);
pause();
}
else
{
printf("fork error\n");
exit(-1);
}
return 0;
}
当代码当中没有wait函数时
父进程阻塞,子进程正常退出,但是子进程内存依然存在
当代码中加入wait函数时
3338为子进程已经不存在了