进程是程序的执行实例,是操作系统进行资源分配和调度的基本单位。每个进程都有自己独立的地址空间和执行状态。
#include <unistd.h>
pid_t fork(void);
示例:
#include <stdio.h>
#include <unistd.h>
int main() {
pid_t pid = fork();
if (pid == 0) {
printf("This is child process, PID: %d\n", getpid());
} else if (pid > 0) {
printf("This is parent process, PID: %d, Child PID: %d\n", getpid(), pid);
} else {
perror("fork failed");
return 1;
}
return 0;
}
#include <unistd.h>
pid_t vfork(void);
#define _GNU_SOURCE
#include <sched.h>
int clone(int (*fn)(void *), void *child_stack, int flags, void *arg, ...);
函数 | 是否刷新I/O缓冲区 | 是否调用终止处理程序 |
---|---|---|
exit | 是 | 是 |
_exit | 否 | 否 |
示例:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
void cleanup() {
printf("Cleanup function called\n");
}
int main() {
atexit(cleanup);
printf("Using exit():\n");
exit(0); // 会调用atexit注册的函数
// 以下代码不会执行
printf("Using _exit():\n");
_exit(0); // 不会调用atexit注册的函数
}
#include <sys/wait.h>
pid_t wait(int *status);
#include <sys/wait.h>
pid_t waitpid(pid_t pid, int *status, int options);
示例:
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <unistd.h>
int main() {
pid_t pid = fork();
if (pid == 0) {
// 子进程
printf("Child process running\n");
sleep(2);
exit(42);
} else if (pid > 0) {
// 父进程
int status;
pid_t child_pid = waitpid(pid, &status, 0);
if (WIFEXITED(status)) {
printf("Child %d exited with status %d\n",
child_pid, WEXITSTATUS(status));
} else {
printf("Child terminated abnormally\n");
}
} else {
perror("fork failed");
return 1;
}
return 0;
}
#include <unistd.h>
extern char **environ;
int execl(const char *path, const char *arg, ...);
int execlp(const char *file, const char *arg, ...);
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 execvpe(const char *file, char *const argv[], char *const envp[]);
函数命名规则: - l:参数列表 - v:参数数组 - p:使用PATH环境变量查找可执行文件 - e:传递环境变量
示例:
#include <stdio.h>
#include <unistd.h>
int main() {
printf("Before exec\n");
// 使用参数列表
execl("/bin/ls", "ls", "-l", NULL);
// 如果exec成功,以下代码不会执行
perror("exec failed");
return 1;
}
#include <unistd.h>
int pipe(int pipefd[2]);
示例:
#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>
#include <string.h>
int main() {
int pipefd[2];
char buf[256];
if (pipe(pipefd) {
perror("pipe failed");
return 1;
}
pid_t pid = fork();
if (pid == 0) {
// 子进程 - 读取数据
close(pipefd[1]); // 关闭写端
read(pipefd[0], buf, sizeof(buf));
printf("Child received: %s\n", buf);
close(pipefd[0]);
} else if (pid > 0) {
// 父进程 - 写入数据
close(pipefd[0]); // 关闭读端
const char *msg = "Hello from parent";
write(pipefd[1], msg, strlen(msg) + 1);
close(pipefd[1]);
wait(NULL);
} else {
perror("fork failed");
return 1;
}
return 0;
}
#include <sys/stat.h>
int mkfifo(const char *pathname, mode_t mode);
#include <signal.h>
int kill(pid_t pid, int sig);
int raise(int sig);
void (*signal(int sig, void (*func)(int)))(int);
#include <sys/shm.h>
int shmget(key_t key, size_t size, int shmflg);
void *shmat(int shmid, const void *shmaddr, int shmflg);
int shmdt(const void *shmaddr);
#include <sys/msg.h>
int msgget(key_t key, int msgflg);
int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg);
#include <sys/sem.h>
int semget(key_t key, int nsems, int semflg);
int semop(int semid, struct sembuf *sops, size_t nsops);
int semctl(int semid, int semnum, int cmd, ...);
ps -eo pid,ni,pri,comm
#include <unistd.h>
#include <sys/resource.h>
int nice(int inc);
int getpriority(int which, id_t who);
int setpriority(int which, id_t who, int prio);
示例:
#include <stdio.h>
#include <unistd.h>
#include <sys/resource.h>
int main() {
// 获取当前优先级
int prio = getpriority(PRIO_PROCESS, 0);
printf("Current priority: %d\n", prio);
// 增加nice值(降低优先级)
nice(5);
prio = getpriority(PRIO_PROCESS, 0);
printf("New priority: %d\n", prio);
return 0;
}
#include <sched.h>
int sched_setscheduler(pid_t pid, int policy, const struct sched_param *param);
int sched_getscheduler(pid_t pid);
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <signal.h>
void daemonize() {
pid_t pid = fork();
if (pid < 0) {
perror("fork failed");
exit(1);
}
if (pid > 0) {
// 父进程退出
exit(0);
}
// 子进程继续
// 创建新会话
if (setsid() < 0) {
perror("setsid failed");
exit(1);
}
// 改变工作目录
if (chdir("/") < 0) {
perror("chdir failed");
exit(1);
}
// 重设文件权限掩码
umask(0);
// 关闭标准文件描述符
close(STDIN_FILENO);
close(STDOUT_FILENO);
close(STDERR_FILENO);
// 处理SIGCHLD信号
signal(SIGCHLD, SIG_IGN);
}
int main() {
daemonize();
// 守护进程主循环
while (1) {
// 守护进程的工作
sleep(10);
}
return 0;
}
ps
:查看进程状态top
:实时进程监控htop
:增强版toppstree
:以树状显示进程kill
:发送信号给进程nice
/renice
:调整进程优先级pgrep
/pkill
:按名称查找/杀死进程/proc/[pid]/
:每个进程的详细信息/proc/[pid]/status
:进程状态/proc/[pid]/cmdline
:启动命令/proc/[pid]/fd/
:打开的文件描述符通过深入理解Linux进程控制,开发者可以编写更高效、更可靠的应用程序,并能够更好地进行系统管理和故障排查。