Linux系统编程入门 - 进程管理与IPC通信
前言
Linux系统编程是深入理解操作系统工作原理的重要途径。本文将介绍Linux下的进程管理、进程间通信(IPC)机制,以及相关的系统调用。
进程基础
进程的创建
在Linux中,进程可以通过fork()系统调用创建:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| #include <stdio.h> #include <unistd.h> #include <sys/wait.h>
int main() { pid_t pid; printf("Before fork\n"); pid = fork(); if (pid == 0) { printf("Child process: PID = %d, Parent PID = %d\n", getpid(), getppid()); sleep(2); printf("Child process exiting\n"); exit(0); } else if (pid > 0) { printf("Parent process: PID = %d, Child PID = %d\n", getpid(), pid); int status; wait(&status); printf("Child process finished with status: %d\n", status); } else { perror("fork failed"); exit(1); } return 0; }
|
进程替换
使用exec系列函数可以替换当前进程的映像:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| #include <stdio.h> #include <unistd.h> #include <sys/wait.h>
int main() { pid_t pid = fork(); if (pid == 0) { char *args[] = {"ls", "-la", NULL}; char *env[] = {NULL}; execve("/bin/ls", args, env); perror("execve failed"); exit(1); } else if (pid > 0) { int status; wait(&status); printf("Child process completed\n"); } else { perror("fork failed"); exit(1); } return 0; }
|
进程间通信(IPC)
1. 管道(Pipe)
管道是最简单的IPC机制,用于父子进程间的通信:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
| #include <stdio.h> #include <unistd.h> #include <string.h> #include <sys/wait.h>
int main() { int pipefd[2]; char buffer[256]; const char *message = "Hello from parent!"; if (pipe(pipefd) == -1) { perror("pipe failed"); exit(1); } pid_t pid = fork(); if (pid == 0) { close(pipefd[1]); read(pipefd[0], buffer, sizeof(buffer)); printf("Child received: %s\n", buffer); close(pipefd[0]); exit(0); } else if (pid > 0) { close(pipefd[0]); write(pipefd[1], message, strlen(message) + 1); close(pipefd[1]); wait(NULL); printf("Parent finished\n"); } else { perror("fork failed"); exit(1); } return 0; }
|
2. 命名管道(FIFO)
命名管道允许不相关进程间通信:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| #include <stdio.h> #include <sys/stat.h> #include <fcntl.h> #include <string.h>
int main() { const char *fifo_name = "/tmp/my_fifo"; char message[] = "Hello from writer!"; mkfifo(fifo_name, 0666); int fd = open(fifo_name, O_WRONLY); if (fd == -1) { perror("open failed"); return 1; } write(fd, message, strlen(message) + 1); close(fd); printf("Writer finished\n"); return 0; }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| #include <stdio.h> #include <fcntl.h> #include <string.h>
int main() { const char *fifo_name = "/tmp/my_fifo"; char buffer[256]; int fd = open(fifo_name, O_RDONLY); if (fd == -1) { perror("open failed"); return 1; } read(fd, buffer, sizeof(buffer)); printf("Reader received: %s\n", buffer); close(fd); unlink(fifo_name); return 0; }
|
3. 共享内存
共享内存是最快的IPC方式:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
| #include <stdio.h> #include <sys/ipc.h> #include <sys/shm.h> #include <string.h> #include <sys/wait.h>
int main() { key_t key = ftok("/tmp", 'A'); int shmid; char *shared_memory; shmid = shmget(key, 1024, IPC_CREAT | 0666); if (shmid == -1) { perror("shmget failed"); exit(1); } shared_memory = shmat(shmid, NULL, 0); if (shared_memory == (char*)-1) { perror("shmat failed"); exit(1); } pid_t pid = fork(); if (pid == 0) { sleep(1); printf("Child read: %s\n", shared_memory); shmdt(shared_memory); exit(0); } else if (pid > 0) { strcpy(shared_memory, "Hello from shared memory!"); printf("Parent wrote data\n"); wait(NULL); shmdt(shared_memory); shmctl(shmid, IPC_RMID, NULL); printf("Parent finished\n"); } else { perror("fork failed"); exit(1); } return 0; }
|
4. 信号量
信号量用于进程同步:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77
| #include <stdio.h> #include <sys/ipc.h> #include <sys/sem.h> #include <sys/wait.h>
int main() { key_t key = ftok("/tmp", 'B'); int semid; semid = semget(key, 1, IPC_CREAT | 0666); if (semid == -1) { perror("semget failed"); exit(1); } union semun { int val; struct semid_ds *buf; unsigned short *array; } sem_union; sem_union.val = 1; semctl(semid, 0, SETVAL, sem_union); pid_t pid = fork(); if (pid == 0) { struct sembuf sem_op; sem_op.sem_num = 0; sem_op.sem_op = -1; sem_op.sem_flg = 0; printf("Child waiting for semaphore...\n"); semop(semid, &sem_op, 1); printf("Child acquired semaphore\n"); sleep(2); sem_op.sem_op = 1; semop(semid, &sem_op, 1); printf("Child released semaphore\n"); exit(0); } else if (pid > 0) { struct sembuf sem_op; sem_op.sem_num = 0; sem_op.sem_op = -1; sem_op.sem_flg = 0; printf("Parent waiting for semaphore...\n"); semop(semid, &sem_op, 1); printf("Parent acquired semaphore\n"); sleep(2); sem_op.sem_op = 1; semop(semid, &sem_op, 1); printf("Parent released semaphore\n"); wait(NULL); semctl(semid, 0, IPC_RMID); printf("Parent finished\n"); } else { perror("fork failed"); exit(1); } return 0; }
|
总结
Linux系统编程涉及多个重要概念:
- 进程管理:fork、exec、wait等系统调用
- 进程间通信:管道、命名管道、共享内存、信号量
- 同步机制:信号量、互斥锁等
掌握这些基础概念对于深入理解操作系统和开发系统级软件非常重要。在实际应用中,需要根据具体需求选择合适的IPC机制。