进程基础概念
在Linux系统中,进程是程序执行的实例,每个进程拥有独立的地址空间、资源和执行状态。内核通过进程描述符(task_struct结构体)管理进程信息。
进程标识符(PID)是唯一标识进程的数字,父进程标识符(PPID)表示创建该进程的父进程。通过getpid()和getppid()系统调用可获取当前进程的PID和PPID。
进程创建与终止
进程创建
通过fork()系统调用创建子进程,子进程复制父进程的代码段、数据段和堆栈。fork()返回两次:
- 父进程中返回子进程PID
- 子进程中返回0
c
#include <unistd.h>
pid_t fork(void);
进程终止
正常终止方式包括:
- 调用
exit()或_exit()函数 - 从
main()函数返回 - 接收到终止信号
exit()会执行标准I/O清理和退出处理程序,而_exit()直接终止进程。
进程间通信(IPC)
管道(Pipe)
匿名管道用于父子进程通信,通过pipe()创建:
c
int pipe(int fd[2]);
共享内存
通过shmget()创建共享内存段,shmat()附加到进程地址空间:
c
int shmget(key_t key, size_t size, int shmflg);
void *shmat(int shmid, const void *shmaddr, int shmflg);
信号(Signal)
使用kill()发送信号,signal()或sigaction()设置信号处理程序:
c
int kill(pid_t pid, int sig);
void (*signal(int sig, void (*func)(int)))(int);
进程状态管理
进程状态
Linux进程主要状态包括:
- 运行(TASK_RUNNING)
- 可中断等待(TASK_INTERRUPTIBLE)
- 不可中断等待(TASK_UNINTERRUPTIBLE)
- 停止(TASK_STOPPED)
- 僵尸(TASK_ZOMBIE)
进程调度
通过nice()调整进程优先级,sched_setscheduler()设置调度策略:
c
int nice(int inc);
int sched_setscheduler(pid_t pid, int policy, const struct sched_param *param);
守护进程
守护进程是在后台运行的独立进程,创建步骤包括:
- 调用
fork()创建子进程,父进程退出 - 调用
setsid()创建新会话 - 改变工作目录到根目录
- 重设文件权限掩码
- 关闭继承的文件描述符
c
pid_t pid = fork();
if (pid > 0) exit(0);
setsid();
chdir("/");
umask(0);
for (int i = 0; i < sysconf(_SC_OPEN_MAX); i++) close(i);
进程监控
进程列表
通过ps命令查看进程信息,或编程方式读取/proc文件系统:
c
DIR *dir = opendir("/proc");
struct dirent *entry;
while ((entry = readdir(dir)) != NULL) {
if (isdigit(entry->d_name[0])) {
printf("PID: %s\n", entry->d_name);
}
}
closedir(dir);
进程资源
getrusage()获取进程资源使用情况:
c
int getrusage(int who, struct rusage *usage);