信号量和信号的处理

时间:2021-01-09 20:40:46






信号(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;
}