看了apue3,关于进程线程和进程间通信写了一个例子,方便自己理解相关知识,备忘。
1 #include <stdlib.h> 2 #include <stdio.h> 3 #include <unistd.h> 4 #include <pthread.h> 5 #include <sys/types.h> 6 #include <sys/ipc.h> 7 #include <sys/shm.h> 8 #include <sys/sem.h> 9 10 //这里全局变量简化线程代码量而已,实际应该在线程获取这些变量再操作。 11 long *shmaddr; 12 int semid; 13 14 /** 15 * 互斥量加或减 16 * @param semid 互斥量id 17 * @param pv 整数加,负数减 18 */ 19 void sem_pv(int semid, short pv) 20 { 21 struct sembuf buf = {0, 0, 0}; 22 buf.sem_op = pv; 23 buf.sem_num = 0; 24 semop(semid, &buf, 1); 25 } 26 27 void thread1(void *arg) 28 { 29 srand((long)arg + time(0)); //(时间 + 索引号)生成随机种子 30 while (1) { 31 sleep(rand() % 8 + 1); //睡眠1~8s 32 sem_pv(semid, -1); //sem - 1,若sem = 1,不阻塞,若sem = 0,阻塞 33 *shmaddr += 1; //共享值 += 线程号 34 printf("This is 1 thread, *shmaddr = %ld!!\n", *shmaddr); 35 sem_pv(semid, +1); //sem + 1,唤醒其他已经阻塞的线程 36 } 37 pthread_exit((arg)); 38 } 39 40 void thread2(void *arg) 41 { 42 srand((long)arg + time(0)); 43 while (1) { 44 sleep(rand() % 8 + 1); 45 sem_pv(semid, -1); 46 *shmaddr += 2; 47 printf("This is 2 thread, *shmaddr = %ld!!\n", *shmaddr); 48 sem_pv(semid, +1); 49 } 50 pthread_exit(arg); 51 } 52 53 void thread3(void *arg) 54 { 55 srand((long)arg + time(0)); 56 while (1) { 57 sleep(rand() % 8 + 1); 58 sem_pv(semid, -1); 59 *shmaddr += 3; 60 printf("This is 3 thread, *shmaddr = %ld!!\n", *shmaddr); 61 sem_pv(semid, +1); 62 } 63 pthread_exit(arg); 64 } 65 66 void thread4(void *arg) 67 { 68 srand((long)arg + time(0)); 69 while (1) { 70 sleep(rand() % 8 + 1); 71 sem_pv(semid, -1); 72 *shmaddr += 4; 73 printf("This is 4 thread, *shmaddr = %ld!!\n", *shmaddr); 74 sem_pv(semid, +1); 75 } 76 pthread_exit(arg); 77 } 78 79 void thread5(void *arg) 80 { 81 srand((long)arg + time(0)); 82 while (1) { 83 sleep(rand() % 8 + 1); 84 sem_pv(semid, -1); 85 *shmaddr += 5; 86 printf("This is 5 thread, *shmaddr = %ld!!\n", *shmaddr); 87 sem_pv(semid, +1); 88 } 89 pthread_exit(arg); 90 } 91 92 void thread6(void *arg) 93 { 94 srand((long)arg + time(0)); 95 while (1) { 96 sleep(rand() % 8 + 1); 97 sem_pv(semid, -1); 98 *shmaddr += 6; 99 printf("This is 6 thread, *shmaddr = %ld!!\n", *shmaddr); 100 sem_pv(semid, +1); 101 } 102 pthread_exit(arg); 103 } 104 105 void thread7(void *arg) 106 { 107 srand((long)arg + time(0)); 108 while (1) { 109 sleep(rand() % 8 + 1); 110 sem_pv(semid, -1); 111 *shmaddr += 7; 112 printf("This is 7 thread, *shmaddr = %ld!!\n", *shmaddr); 113 sem_pv(semid, +1); 114 } 115 pthread_exit(arg); 116 } 117 118 void thread8(void *arg) 119 { 120 srand((long)arg + time(0)); 121 while (1) { 122 sleep(rand() % 8 + 1); 123 sem_pv(semid, -1); 124 *shmaddr += 8; 125 printf("This is 8 thread, *shmaddr = %ld!!\n", *shmaddr); 126 sem_pv(semid, +1); 127 } 128 pthread_exit(arg); 129 } 130 131 typedef void (*thread)(void *arg); 132 #define PROJ_ID 8 133 int main(int argc, char const *argv[]) 134 { 135 pid_t pid[4]; 136 pthread_t thid[8]; 137 thread fun[8] = {thread1, thread2, thread3, thread4, thread5, thread6, thread7, thread8}; 138 key_t key; 139 int shmid; 140 int i; 141 long index; //这里使用long是(void *)<---->long,long和指针占用内存大小(主机64bit)一样,否则gcc会报warnning 142 union semun { 143 int val; 144 struct semid_ds *buf; 145 unsigned short *array; 146 } semopts; 147 148 if ((key = ftok("." , PROJ_ID )) == -1) { 149 perror("ftok error"); 150 exit(1); 151 } 152 if ((shmid = shmget(key, sizeof(long), IPC_CREAT | 0666)) == -1) { 153 perror("shmget error"); 154 exit(1); 155 } 156 if ((shmaddr = (long *)shmat(shmid, NULL, 0)) == (long *) - 1) { 157 perror("shmat error"); 158 exit(1); 159 } 160 *shmaddr = 0; //初始化共享量 161 162 if ((semid = semget(key, 1, IPC_CREAT | 0666)) == -1) { 163 perror("semget failed"); 164 exit(1); 165 } 166 semopts.val = 1; //信号量初始为1 167 168 if (semctl(semid, 0, SETVAL, semopts) == -1) { 169 perror("semctl failed"); 170 exit(1); 171 } 172 //创建4进程 & 8线程 173 for (i = 0; i < 4; ++i) { 174 pid[i] = fork(); 175 if (pid[i] == 0) { 176 index = 2 * i; 177 if (pthread_create(&thid[index], NULL, (void *)fun[index], (void *)index) != 0) { 178 perror("thread error"); 179 exit(1); 180 } 181 index++; 182 if (pthread_create(&thid[index], NULL, (void *)fun[index], (void *)index) != 0) { 183 perror("thread error"); 184 exit(1); 185 } 186 sleep(1); 187 printf("This is %d process\n", i); 188 printf("Children‘s pid = %d, ppid = %d\n", getpid(), getppid()); 189 while (1) 190 sleep(10); 191 exit(0); 192 193 } else if (pid[i] < 0) { 194 perror("fork error"); 195 exit(1); 196 } 197 } 198 //父进程退出,4个子进程成为孤儿进程 199 exit(0); 200 }
程序开启4进程8线程同时一起累加。线程可以用全局变量同步,但4个子进程间不能共享累加结果,需要用进程共享量。同时涉及到多线程多进程的并发,需要用进程互斥量。
时间: 2024-10-10 23:30:24