5分钟速通【Linux进程】

写在前面:

兄弟们,我手里有个长期项目,考虑接私活的可以看看我GitHub!

https://github.com/ccy-233/coder2retire

1. 什么是进程?
  • 进程就是运行中的程序,是系统资源分配的基本单位

  • 每个进程都有唯一的PID(进程ID)

  • 进程有父子关系,通过ps -ef可以查看

2. 进程的创建 - fork()
pid_t pid = fork();

- 简单理解:fork()就像细胞分裂,一个变两个

  • 调用一次,返回两次:父进程得到子进程PID,子进程得到0

  • 子进程是父进程的复制品

3. 进程的程序替换 - exec族
execl("/bin/ls", "ls", "-l", NULL);

- 保留进程ID,但内容完全变成新程序

  • 就像换灵魂:外壳不变,内在全变

  • 常用函数:execl, execlp, execle, execv, execvp等

4. 进程的等待与回收 - wait/waitpid
pid_t wait(int *status); pid_t waitpid(pid_t pid, int *status, int options);

- 父进程等待子进程结束并回收资源

  • 避免僵尸进程(zombie)的产生

  • waitpid比wait更灵活,可以非阻塞等待

5. 进程的退出

exit(0);    // 标准C库函数

_exit(0);   // 系统调用

  • exit会刷新缓冲区,exit直接退出

  • 返回值0表示正常退出

一. 文件操作与I/O

1. 文件描述符
  • 就像文件的"身份证号码"

  • 标准输入(0)、标准输出(1)、标准错误(2)

  • 每个进程最多可打开的文件数有限制

2. 文件操作基本函数
// 打开文件 int fd = open("test.txt", O_RDWR | O_CREAT, 0644); // 读取文件 char buf[1024]; int n = read(fd, buf, sizeof(buf)); // 写入文件 write(fd, "hello", 5); // 关闭文件 close(fd); // 文件指针定位 lseek(fd, 0, SEEK_SET);  // 回到文件开头
3. 文件属性获取
struct stat st; stat("file.txt", &st);   - 获取文件大小:st.st_size
  • 判断文件类型:S_ISREG(st.st_mode)、S_ISDIR(st.st_mode)
4. 目录操作
DIR *dir = opendir("."); struct dirent *entry; while ((entry = readdir(dir)) != NULL) {     printf("%s\n", entry->d_name); } closedir(dir);

三、进程间通信(IPC)

1. 管道通信
int fd[2]; pipe(fd);  // fd[0]读端,fd[1]写端
  • 单向通信:水管模型,一端进一端出

  • 只能用于有亲缘关系的进程

  • 适合简单的数据传输

2. 命名管道(FIFO)
// 创建命名管道 mkfifo("myfifo", 0644); // 使用方法与普通文件类似 int fd = open("myfifo", O_WRONLY);

- 可用于无关进程间通信

  • 遵循先进先出原则
3. 信号通信
// 信号处理函数 void sig_handler(int signo) {     printf("收到信号: %d\n", signo); } // 设置信号处理 signal(SIGINT, sig_handler);

- 常见信号:

  • SIGINT (2): Ctrl+C中断

  • SIGKILL (9): 强制终止(不可捕获)

  • SIGTERM (15): 终止信号

  • SIGCHLD (17): 子进程状态改变

  • SIGALRM (14): 定时器到期

四、实用示例

1. 创建守护进程
void daemonize() {     pid_t pid = fork();     if (pid < 0) exit(1);     if (pid > 0) exit(0);  // 父进程退出          setsid();  // 创建新会话          // 关闭标准输入输出错误     close(0);     close(1);     close(2);     // ...更多操作 }
2. 简单shell实现
while (1) {     printf("myshell> ");     fgets(cmd, sizeof(cmd), stdin);          if (fork() == 0) {         // 子进程执行命令         execlp(cmd, cmd, NULL);         exit(0);     } else {         // 父进程等待         wait(NULL);     } }

五、常见错误与调试技巧

1. 经典错误
  • 僵尸进程:子进程结束但未被回收

  • 孤儿进程:父进程先于子进程结束

  • 内存泄漏:申请的内存未释放

  • 文件描述符泄漏:打开文件未关闭

2. 调试工具
  • strace:跟踪系统调用

  • gdb:代码调试器

  • valgrind:内存错误检测

  • lsof:查看打开的文件

你可能感兴趣的:(linux,运维,服务器)