信号(Signal)
信号的概念
信号是信息的载体,通常是以某种物理量表现出来的。通信技术不同,采用的传输信号形式就不同。信号的特性:信号必须是可变化、可观测和可实现的某种物理量。
信号量卖票系统,几个机器运行同一段代码,但是票不会重复,信号有pv操作
头文件
#ifndef __SEMAPHORE_H__
#define __SEMAPHORE_H__
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
union semun
{
int val; /* Value for SETVAL */
struct semid_ds *buf; /* Buffer for IPC_STAT, IPC_SET */
unsigned short *array; /* Array for GETALL, SETALL */
struct seminfo *__buf; /* Buffer for IPC_INFO
(Linux specific) */
};
// 信号量的初始化函数
int sem_init(int sem_id)
{
union semun sem;
sem.val = 1;
int ret = semctl(sem_id, 0, SETVAL, sem);
return ret;
}
// 信号量的 P 操作
int sem_p(int sem_id)
{
struct sembuf sem;
sem.sem_num = 0;
sem.sem_op = -1;
sem.sem_flg = SEM_UNDO;
int ret = semop(sem_id, &sem,1);
return ret;
}
// 信号量的 v 操作
int sem_v(int sem_id)
{
struct sembuf sem;
sem.sem_num = 0;
sem.sem_op = 1;
sem.sem_flg = SEM_UNDO;
int ret = semop(sem_id, &sem,1);
return ret;
}
// 销毁信号量
int sem_del(int sem_id)
{
int ret = semctl(sem_id, 0, IPC_RMID);
return ret;
}
#endif // __SEMAPHORE_H__
售票系统 #include <stdio.h> #include <sys/ipc.h> #include <sys/shm.h> #include <sys/types.h> #include <string.h> #include <time.h> #include "semaphore.h" typedef struct _shm { int flag; int ticket; }SHM; void sellTicket(SHM* pshm, int sem_id) { while (1) { int time = rand() % 10 + 1; usleep(time*100000); // 信号量的P操作 sem_p (sem_id); if (pshm->ticket == 0) // 票卖完 { sem_v (sem_id); break; } printf ("卖掉一张票,座位号是 : %d\n", pshm->ticket); pshm->ticket--; sem_v (sem_id); } } int main(int argc, char **argv) { srand ((unsigned int)time(NULL)); // 1、创建或者获取一个共享内存 int shmid = shmget((key_t)1234, sizeof(SHM), 0666 | IPC_CREAT); if (shmid == -1) { perror ("shmget"); return -1; } // 创建一个信号量 int sem_id = semget((key_t)5678, 1, 0666 | IPC_CREAT); if (sem_id== -1) { perror ("semget"); return -1; } // 2、将共享内存映射到当前的进程空间 SHM* pshm = (SHM*)shmat(shmid, NULL, 0); if(pshm == (SHM*)-1) { perror ("shmat"); return -1; } // 如果命令行参数等于2 负责对共享内存和信号量进行初始化 if (argc == 2) { pshm->ticket = 100; sem_init(sem_id); } // 开始卖票 sellTicket(pshm, sem_id); // 如果命令行参数等于2 负责对共享内存和信号量进行删除 if (argc == 2) { shmctl(shmid, IPC_RMID, NULL); sem_del(sem_id); } return 0; }
捕捉信号
signal.c #include <stdio.h> #include <signal.h> // 信号处理函数 void handle(int signum) { printf ("捕捉到一个信号 %d\n", signum); } int main() { signal(SIGINT, handle); signal(SIGTERM, handle); while (1); return 0; }
通过信号杀死一个进程
#include <stdio.h> #include <signal.h> int main() { //while (1) { kill (18027,9); sleep(1); } return 0; }
信号定时器
#include <stdio.h> #include <signal.h> // 信号处理函数 void handle(int signum) { printf ("hello world\n"); // 定时器重置 alarm(2); } int main() { // 定时器是一次性的 alarm(2); signal(SIGALRM, handle); while (1); return 0; }
sigaction.c
#include <stdio.h> #include <signal.h> // 信号处理函数 void handle(int signum) { printf ("hello world\n"); // 定时器重置 alarm(2); } int main() { // 定时器是一次性的 alarm(2); struct sigaction act; act.sa_handler = handle; sigaction(SIGALRM, &act, NULL); while (1); return 0; }
处理子进程的退出
#include <stdio.h> #include <signal.h> #include <sys/types.h> #include <sys/wait.h> // 信号处理函数 void handle(int signum) { while (waitpid (-1, NULL, WNOHANG) > 0) { printf ("捕获一个子进程\n"); } printf ("111111\n"); } int main() { signal (SIGCHLD, handle); int count = 10; while (count--) { pid_t pid = fork(); switch (pid) { case -1: perror ("fork"); break; case 0: // 子进程 printf ("我是子进程,我的Id 是%d\n", getpid()); sleep(1); exit(0); default: // 父进程 printf ("我是父进程,Id = %d\n", getpid()); break; } } while (1); return 0; }