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 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167
| #define _GNU_SOURCE #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/types.h> #include <sys/ipc.h> #include <sys/sem.h> #include <errno.h> #include <string.h>
// 信号量操作联合体 union semun { int val; // 用于SETVAL struct semid_ds *buf; // 用于IPC_STAT和IPC_SET unsigned short *array; // 用于GETALL和SETALL };
int main() { key_t key; int semid; union semun arg; struct semid_ds sem_info; printf("=== Semctl函数示例 ===\n"); // 创建信号量集 key = ftok(".", 'c'); if (key == -1) { perror("ftok失败"); exit(EXIT_FAILURE); } // 先尝试删除可能存在的同名信号量集 semid = semget(key, 1, 0666); if (semid != -1) { semctl(semid, 0, IPC_RMID); } // 创建包含3个信号量的信号量集 semid = semget(key, 3, 0666 | IPC_CREAT | IPC_EXCL); if (semid == -1) { perror("创建信号量集失败"); exit(EXIT_FAILURE); } printf("成功创建信号量集,标识符: %d\n", semid); // 示例1: 设置单个信号量的值 printf("\n示例1: 设置单个信号量的值\n"); // 设置信号量0的值为5 arg.val = 5; if (semctl(semid, 0, SETVAL, arg) == -1) { perror("设置信号量0失败"); } else { printf(" 成功设置信号量0的值为: %d\n", semctl(semid, 0, GETVAL)); } // 设置信号量1的值为10 arg.val = 10; if (semctl(semid, 1, SETVAL, arg) == -1) { perror("设置信号量1失败"); } else { printf(" 成功设置信号量1的值为: %d\n", semctl(semid, 1, GETVAL)); } // 设置信号量2的值为0 arg.val = 0; if (semctl(semid, 2, SETVAL, arg) == -1) { perror("设置信号量2失败"); } else { printf(" 成功设置信号量2的值为: %d\n", semctl(semid, 2, GETVAL)); } // 示例2: 获取单个信号量的值 printf("\n示例2: 获取单个信号量的值\n"); int val0 = semctl(semid, 0, GETVAL); int val1 = semctl(semid, 1, GETVAL); int val2 = semctl(semid, 2, GETVAL); if (val0 != -1 && val1 != -1 && val2 != -1) { printf(" 信号量0的值: %d\n", val0); printf(" 信号量1的值: %d\n", val1); printf(" 信号量2的值: %d\n", val2); } else { perror("获取信号量值失败"); } // 示例3: 批量设置所有信号量的值 printf("\n示例3: 批量设置所有信号量的值\n"); unsigned short values[3] = {3, 7, 2}; arg.array = values; if (semctl(semid, 0, SETALL, arg) == -1) { perror("批量设置信号量值失败"); } else { printf(" 成功批量设置信号量值\n"); // 验证设置结果 unsigned short get_values[3]; arg.array = get_values; if (semctl(semid, 0, GETALL, arg) == -1) { perror("批量获取信号量值失败"); } else { printf(" 当前信号量值: [%d, %d, %d]\n", get_values[0], get_values[1], get_values[2]); } } // 示例4: 获取信号量集状态信息 printf("\n示例4: 获取信号量集状态信息\n"); arg.buf = &sem_info; if (semctl(semid, 0, IPC_STAT, arg) == -1) { perror("获取信号量集状态失败"); } else { printf(" 信号量集状态信息:\n"); printf(" 键值: %d\n", sem_info.sem_perm.__key); printf(" 信号量数量: %ld\n", sem_info.sem_nsems); printf(" 最后操作时间: %ld\n", sem_info.sem_otime); printf(" 最后修改时间: %ld\n", sem_info.sem_ctime); printf(" 创建者UID: %d\n", sem_info.sem_perm.cuid); printf(" 创建者GID: %d\n", sem_info.sem_perm.cgid); printf(" 所有者UID: %d\n", sem_info.sem_perm.uid); printf(" 所有者GID: %d\n", sem_info.sem_perm.gid); printf(" 权限: %o\n", sem_info.sem_perm.mode); } // 示例5: 修改信号量集权限 printf("\n示例5: 修改信号量集权限\n"); struct semid_ds new_info; memcpy(&new_info, &sem_info, sizeof(struct semid_ds)); new_info.sem_perm.mode = 0644; // 修改为读写权限 arg.buf = &new_info; if (semctl(semid, 0, IPC_SET, arg) == -1) { perror("修改信号量集权限失败"); } else { printf(" 成功修改信号量集权限为: %o\n", new_info.sem_perm.mode); } // 示例6: 错误处理演示 printf("\n示例6: 错误处理演示\n"); // 尝试操作不存在的信号量集 if (semctl(999999, 0, GETVAL) == -1) { printf(" 操作不存在的信号量集: %s\n", strerror(errno)); } // 尝试操作不存在的信号量索引 if (semctl(semid, 999, GETVAL) == -1) { printf(" 操作不存在的信号量索引: %s\n", strerror(errno)); } // 示例7: 删除信号量集 printf("\n示例7: 删除信号量集\n"); if (semctl(semid, 0, IPC_RMID) == -1) { perror("删除信号量集失败"); } else { printf(" 成功删除信号量集 %d\n", semid); // 验证删除结果 if (semctl(semid, 0, GETVAL) == -1) { printf(" 验证: 信号量集已不存在\n"); } } return 0; }
|