1.signal 设置信号处理方式
#include <signal.h> //所需头文件
typedef void (*sighandler_t)(int);
sighandler_t signal(int signum, sighandler_t handler);
//int signum(指定信号编号(kill -l))
//ighandler_t handler(SIG_IGN:忽略参数signum指定的信号;自定义信号函数处理指针)
2.验证signal函数
#include <signal.h>
#include <stdio.h>
void handler (int signum)
{
switch(signum){
case 2:
printf("this is SIGINT\n");
break;
case 9:
printf("this is SIGKILL\n");
break;
case 10:
printf("this is SIGUSR!\n");
break;
}
printf("get signum :%d\n",signum);
printf("jiubu guandiao\n");
}
int main()
{
signal(SIGINT,handler); //自定义信号函数处理指针
// signal(SIGINT,SIG_IGN);
signal(SIGKILL,handler);
// signal(SIGKILL,SIG_IGN); //SIG_IGN:忽略参数signum指定的信号
signal(SIGUSR1,handler);
// signal(SIGUSR1,SIG_IGN);
while(1);
return 0;
}
3.kill信号处理发送函数
#include <sys/types.h>
#include <signal.h>
int kill(pid_t pid, int sig);
//pid_t pid(进程的pid号,可用ps aux|grep a.out(进程名))
//int sig(代表的信号编号)
4.sprintf把格式化的数据写入某个字符串
#include <stdio.h>
int sprintf(char *str, const char *format, ...);//制作一个指令,放在char *str,然后再使用system()调用。
//char *str(存放数据的字符串)
//const char *format(格式化字符串,即在程序中想要的格式)
5.验证kill函数和sprintf函数
#include <stdio.h>
#include <sys/types.h>
#include <signal.h>
int main(int arge,char **argv)
{
int signum;
int pid;
char buf[128] = {0};
signum = atoi(argv[1]); //将第一个输入 转换成整型数
pid = atoi(argv[2]); //将第二个输入 转换成整型数
printf("signum:%d pid:%d\n",signum,pid);
// kill(pid,signum);
sprintf(buf,"kill %d %d",signum,pid);
system(buf);
return 0;
}
6.sigaction 查询和设置信号处理方式
#include <signal.h>
int sigaction(int signum, const struct sigaction *act,struct sigaction *oldact);
//int signum(可以指定SIGKILL和SIGSTOP以外的所有信号)
//const struct sigaction *act(设置指针指向结构体)
/*
struct sigaction {
void (*sa_handler)(int); //信号处理程序,不接受额外数据,SIG_IGN 为忽略,SIG_DFL 为默认动作
void (*sa_sigaction)(int, siginfo_t *, void *); //信号处理程序,能够接受额外数据和sigqueue配合使用(要配)
sigset_t sa_mask;//阻塞关键字的信号集,可以再调用捕捉函数之前,把信号添加到信号阻塞字,信号捕捉函数返回之前恢复为原先的值(默认阻塞,可不配置)。
int sa_flags;//影响信号的行为SA_SIGINFO表示能够接受数据(接收一定要加的)
};
*/
//struct sigaction *oldact(NULL)
7.验证sigaction函数(接收)
#include <signal.h>
#include <stdio.h>
//void (*sa_sigaction)(int, siginfo_t *, void *);
void handler(int signum,siginfo_t *info,void *context)
{
printf("get signum:%d\n",signum);//获取信号排列数
if(context != NULL){ //判断context中是否有内容,再进行结构体指针的调用
printf("get data:%d\n",info->si_int);
printf("get data:%d\n",info->si_value.sival_int);
printf("from pro pid:%d\n",info->si_pid);
}
}
int main()
{
struct sigaction sig; //定义sig类结构体
printf("pid=%d\n",getpid());
sig.sa_sigaction = handler; //定义sa_sigaction=handler函数
sig.sa_flags = SA_SIGINFO; //设置信号处理函数是带有三个参数的sa_sigaction
//int sigaction(int signum, const struct sigaction *act,struct sigaction *oldact);
sigaction(SIGUSR1,&sig,NULL);
while(1);
return 0;
}
8.sigqueue信号的发送携带数据
#include <signal.h>
int sigqueue(pid_t pid, int sig, const union sigval value);
//pid_t pid(进程的pid号,可用ps aux|grep a.out(进程名))
//int sig(代表的信号编号)
//const union sigval value(携带的数据)
union sigval {
int sival_int;//数据
void *sival_ptr;
};
9.验证sigqueue函数(发送)
#include <stdio.h>
#include <signal.h>
// int sigqueue(pid_t pid, int sig, const union sigval value);
int main(int arge,char **argv)
{
int pid;
int signum;
signum = atoi(argv[1]);
pid = atoi(argv[2]);
union sigval value;
value.sival_int = "lixiang";
sigqueue(pid,signum,value);
printf("pid:%d\n",getpid());
return 0;
}
10.信号量
#include <sys/sem.h>
#include <sys/types.h>
#include <sys/ipc.h>
int semget(key_t key, int num_sems, int sem_flags);// 创建或获取一个信号量组:若成功返回信号量集ID,失败返回-1
//key_t key = key_t ftok(const char *pathname, int proj_id);
//int num_sems(创建信号量集中信号量的个数)
//int sem_flags(如果内核中不存在键值与key相等的信号量集,则新建一个信号量集(IPC_CREAT|0666);如果存在这样的信号量集,返回此信号量集的标识符)
int semop(int semid, struct sembuf semoparray[], size_t numops); // 对信号量组进行操作(P、V),改变信号量的值:成功返回0,失败返回-1
//int semid(semget返回信号量集ID)
//struct sembuf semoparray[](指向进行操作的信号量集结构体数组的首地址)
//size_t numops(进行操作信号量的个数)
int semctl(int semid, int sem_num, int cmd, union semun arg);// 控制信号量的相关信息
//int semid(semget返回信号量集ID)
//int sem_num(表示某一个信号量,0为第一个 )
//int cmd(IPC_RMID)从内核中删除信号量集合
//int cmd(SETVAL)用联合体中val成员的值设置信号量集合中单个信号量的值
//union semun arg(结构体)
11.实现信号量
#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
// int semget(key_t key, int nsems, int semflg);
//int semctl(int semid, int semnum, int cmd, ...);
//int semop(int semid, struct sembuf *sops, unsigned nsops);
void pGetKey(int id)
{
struct sembuf set;
set.sem_num = 0;
set.sem_op = -1; //将信号量对象中序号为0的信号量减1
set.sem_flg = SEM_UNDO;
semop(id,&set,1);
printf("get key\n");
}
void vBackKey(int id)
{
struct sembuf set;
set.sem_num = 0;
set.sem_op = 1; //将信号量对象中序号为0的信号量加1
set.sem_flg = SEM_UNDO;//可以避免因为进程异常退出而造成的死锁
semop(id,&set,1);
printf("back key\n");
}
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 main(int arge , char **argv)
{
int semid;
key_t key;
key = ftok(".",2);
semid = semget(key,1,IPC_CREAT|0666); //创建一个信号量组,返回信号量集ID;1表示只有一个信号量
union semun initsem;
initsem.val = 0;//锁的个数 //SETVAL用的值
semctl(semid,0,SETVAL,initsem);//创建一个信号量集对象
int pid = fork(); //创建一个进程
if(pid > 0){
pGetKey(semid); //2.P操作,拿走一个钥匙(等待钥匙)
printf("this is father\n");
vBackKey(semid); //3.V操作,放回一个钥匙
semctl(semid,0,IPC_RMID); //4.从内核中删除信号量集合
}else if(pid == 0){
printf("this is chile\n");
vBackKey(semid); //1.V操作,放入一个钥匙
}else{
printf("chuanjian shibai\n");
}
return 0;
}
12.配合共享内存使用信号量
1.读数据
#include <stdio.h>
#include <sys/shm.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) */
};
void PGetKey(int semid)
{
struct sembuf sops;
sops.sem_num = 0; /* Operate on semaphore 0 */
sops.sem_op = -1; /* Wait for value to equal 0 */
sops.sem_flg = SEM_UNDO;
semop(semid, &sops, 1);
printf("get key\n");
}
void VReturnKey(int semid)
{
struct sembuf sops;
sops.sem_num = 0; /* Operate on semaphore 0 */
sops.sem_op = 1; /* Wait for value to equal 0 */
sops.sem_flg = SEM_UNDO;
semop(semid, &sops, 1);
printf("return key\n");
}
int main()
{
key_t key;
int shmid;
int semid;
char *pShmAdd;
key = ftok(".",1);
//int shmget(key_t key, size_t size, int msgflg);
shmid = shmget(key,1024*4,IPC_CREAT|0666);
//void *shmat(int shm_id, const void *addr, int flag);
pShmAdd = shmat(shmid,0,0);
semid = semget(key, 1, IPC_CREAT|0666);
if(semid == -1){
printf("creation file\n");
}
union semun arg;
arg.val =0;
semctl(semid,0, SETVAL,arg);
PGetKey(semid);
printf("read:%s\n",pShmAdd);
VReturnKey(semid);
shmdt(pShmAdd);
semctl(semid,0, IPC_RMID);
shmctl(shmid,IPC_RMID,0);
return 0;
}
2.写数据
#include <stdio.h>
#include <sys/shm.h>
#include <string.h>
#include <sys/ipc.h>
#include <sys/sem.h>
void PGetKey(int semid)
{
struct sembuf sops;
sops.sem_num = 0; /* Operate on semaphore 0 */
sops.sem_op = -1; /* Wait for value to equal 0 */
sops.sem_flg = SEM_UNDO;
semop(semid, &sops, 1);
printf("get key\n");
}
void VReturnKey(int semid)
{
struct sembuf sops;
sops.sem_num = 0; /* Operate on semaphore 0 */
sops.sem_op = 1; /* Wait for value to equal 0 */
sops.sem_flg = SEM_UNDO;
semop(semid, &sops, 1);
printf("return key\n");
}
int main()
{
key_t key;
int shmid;
int semid;
char *pShmAdd;
key = ftok(".",1);
//int shmget(key_t key, size_t size, int msgflg);
shmid = shmget(key,1024*4,0);
//void *shmat(int shm_id, const void *addr, int flag);
pShmAdd = shmat(shmid,0,0);
strcpy(pShmAdd,"LiXiang 123456\n");
semid = semget(key, 0, 0);
if(semid == -1){
printf("creation file\n");
}
VReturnKey(semid);
shmdt(pShmAdd);
return 0;
}