linux信号 信号量和进程间通信

signal

#include <stdio.h>
#include <unistd.h>
#include <signal.h>

void fa(int signo){
  printf("捕获了信号%d\n",signo);
  alarm(1);//新闹钟,实现循环的效果
}
int main(){
  signal(SIGALRM,fa);
  alarm(5);
  sleep(3);
  int res = alarm(5);
  printf("res=%d\n",res);
  //alarm(0);//取消所有闹钟
  while(1);
}

信号列表查看 http://www.2cto.com/os/201202/119425.html

kill

#include <stdio.h>
#include <unistd.h>
#include <signal.h>

void fa(int signo){
  printf("捕获了信号%d\n",signo);
}
int main(){
  //signal(SIGINT,fa);//父进程执行,子进程继承
  pid_t pid = fork();
  //signal(SIGINT,fa);//父子进程分别执行
  if(pid == 0){
    signal(SIGINT,fa);
	printf("pid=%d\n",getpid());
	while(1);
  }
  usleep(10);
  kill(pid,SIGINT);
  printf("信号已经发送完毕\n");
  return 0;
}

raise

#include <stdio.h>
#include <signal.h>

void fa(int signo){
  printf("捕获了信号%d\n",signo);
}
int main(){
  signal(SIGINT,fa);
  int res = sleep(10);//会被信号打断,返回剩余秒数
  printf("res=%d\n",res);
  raise(SIGINT);//给自己发了信号2
  while(1);
}

#include <stdio.h>
#include <unistd.h>
#include <signal.h>

void fa(int signo){
  printf("捕获了信号%d\n",signo);
}
int main(){
  signal(SIGINT,fa); // 信号2自定义
  signal(SIGQUIT,SIG_IGN);//信号3被忽略
  pid_t pid = fork();
  if(pid == 0){//fork()的子进程信号处理与父进程一样
    printf("pid=%d\n",getpid());
	while(1);
  }
  printf("父进程结束\n");
  return 0;
}

sigprocmask

#include <stdio.h>
#include <signal.h>

void fa(int signo){
  printf("捕获到了信号%d\n",signo);
}
int main(){
  signal(SIGINT,fa); signal(SIGQUIT,fa);
  signal(50,fa);
  printf("pid=%d\n",getpid());
  printf("执行普通代码,没有屏蔽信号\n");
  sleep(15);
  printf("执行关键代码,开始信号屏蔽\n");
  sigset_t set,old;//set屏蔽,old解除
  sigemptyset(&set); sigaddset(&set,50); 
  sigaddset(&set,2); sigaddset(&set,3);
  sigprocmask(SIG_SETMASK,&set,&old);//开始屏蔽
  sleep(15); printf("屏蔽被解除\n");
  sigprocmask(SIG_SETMASK,&old,0);//解除屏蔽
}//50是可靠信号,所以不丢失;2 3是不可靠信号 会丢失


#include <stdio.h>
#include <unistd.h>
#include <signal.h>

void fa(int signo){
  printf("捕获了信号%d\n",signo);
}
int main(){
  signal(SIGINT,fa); // 信号2自定义
  signal(SIGQUIT,SIG_IGN);//信号3被忽略
  pid_t pid = vfork();
  if(pid == 0){
    printf("pid=%d\n",getpid());
	execl("./proc","proc",NULL);
  }
  printf("父进程结束\n");
  return 0;
}

计时器

#include <stdio.h>
#include <sys/time.h>
#include <signal.h>

void fa(int signo){
  printf("每隔1.1秒执行一次\n");
}
int main(){
  signal(SIGALRM,fa);
  struct itimerval timer;
  //间隔时间
  timer.it_interval.tv_sec = 1;//秒数
  timer.it_interval.tv_usec = 100000;//微秒
  //开始时间
  timer.it_value.tv_sec = 5;
  timer.it_value.tv_usec = 0;
  setitimer(ITIMER_REAL,&timer,0);//启动计时器
  while(1);
}

消息队列

  IPC结构的相关命令:
   ipcs  查看IPC结构
    -a 显示所有的IPC结构
    -m 显示 共享内存
    -q 显示 消息队列
    -s 显示 信号量集
   ipcrm 删除IPC结构
    选项和ipcs 基本一样,但在选项后需要加上IPC结构的ID。

#include <stdio.h>
#include <stdlib.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <unistd.h>
#include <string.h>
struct MSG{
  long mtype;
  char buf[256];
};
int main(){
  key_t key = ftok(".",100);
  int msgid = msgget(key,0666|IPC_CREAT);
  if(msgid == -1) perror("msgget"),exit(-1);
  struct MSG msg1,msg2;
  msg1.mtype = 1; strcpy(msg1.buf,"zhangfei");
  msg2.mtype = 2; strcpy(msg2.buf,"guanyu");
  int res = msgsnd(msgid,&msg1,sizeof(msg1.buf),0);
  if(res == -1) perror("msgsnd msg1"),exit(-1);
  res = msgsnd(msgid,&msg2,sizeof(msg2.buf),0);
  if(res == -1) perror("msgsnd msg2"),exit(-1);
  printf("发送成功\n");
  return 0;
}


#include <stdio.h>
#include <stdlib.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <unistd.h>
#include <string.h>
struct MSG{
  long mtype;
  char buf[256];
};
int main(){
  key_t key = ftok(".",100);
  int msgid = msgget(key,0);
  if(msgid == -1) perror("msgget"),exit(-1);
  struct MSG msg1;
  int res=msgrcv(msgid,&msg1,sizeof(msg1.buf),-2,0);
  if(res == -1) perror("msgsnd msg1"),exit(-1);
  printf("%s\n",msg1.buf);
  return 0;
}


ipc共享内存


#include <stdio.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdlib.h>
#include <unistd.h>

int main(){
  key_t key = ftok(".",100);//创建key,路径只要存在
  if(key == -1) perror("ftok"),exit(-1);//key就没错
  int shmid = shmget(key,4,0666|IPC_CREAT|IPC_EXCL);
  if(shmid == -1) perror("shmget"),exit(-1);
  printf("共享内存创建成功\n");
  void* p = shmat(shmid,0,0);//挂接
  if(p == (void*)-1) perror("shmat"),exit(-1);
  int* pi = p;
  *pi = 100;//存入共享内存
  shmdt(p);//脱接
  return 0;
}//练习:写shmb.c,把100从共享内存中取出并打印


#include <stdio.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdlib.h>
#include <unistd.h>

int main(){
  key_t key = ftok(".",100);//创建key,路径只要存在
  if(key == -1) perror("ftok"),exit(-1);//key就没错
  int shmid = shmget(key,0,0);
  if(shmid == -1) perror("shmget"),exit(-1);
  void* p = shmat(shmid,0,0);//挂接
  if(p == (void*)-1) perror("shmat"),exit(-1);
  printf("%d\n",*(int*)p); 
  shmdt(p);//脱接
  return 0;
}

#include <stdio.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdlib.h>
#include <unistd.h>

int main(){
  key_t key = ftok(".",100);
  int shmid = shmget(key,0,0);
  if(shmid == -1) perror("shmget"),exit(-1);
  struct shmid_ds ds;
  shmctl(shmid,IPC_STAT,&ds);//查询
  printf("key=%x,%x\n",key,ds.shm_perm.__key);
  printf("size=%d\n",ds.shm_segsz);
  printf("mode=%o\n",ds.shm_perm.mode);
  printf("nattch=%d\n",ds.shm_nattch);
  ds.shm_perm.mode = 0600;//准备修改,权限能改
  ds.shm_segsz = 400;//大小不能改
  shmctl(shmid,IPC_SET,&ds);//修改共享内存
  //shmctl(shmid,IPC_RMID,0);//删除共享内存
  return 0;
}

信号量

#include <stdio.h>
#include <stdlib.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <signal.h>

int semid;//全局变量,两个函数都可以使用
void fa(int signo){//3
  printf("服务器即将关闭\n");
  semctl(semid,0,IPC_RMID);//删除信号量集
  exit(0);
}
int main(){//只是建了一个计数器的数组
  key_t key = ftok(".",100);
  semid = semget(key,1,0666|IPC_CREAT);
  if(semid == -1) perror("semget"),exit(-1);
  semctl(semid,0,SETVAL,5);//允许5个进行并行访问
  printf("信号量初始化成功\n");
  signal(SIGINT,fa);//1
  while(1);//2
}



#include <stdio.h>
#include <stdlib.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <unistd.h>

int main(){
  key_t key = ftok(".",100);
  int semid = semget(key,0,0);//获取时只需要key
  if(semid == -1) perror("semget"),exit(-1);
  int i;
  for(i=0;i<10;i++){//启动10个子进程
    pid_t pid = fork();
	if(pid == 0){//子进程的分支
	  struct sembuf op;
	  op.sem_num = 0;//下标
	  op.sem_op = -1;//减1,进程是新增
	  op.sem_flg = 0;//阻塞,如果非阻塞用IPC_NOWAIT
	  semop(semid,&op,1);//数组的地址=数组首元素地址
	  printf("访问共享资源\n");//如计数为0阻塞在19行
      sleep(5); printf("共享资源访问完毕\n");
	  op.sem_op = 1;//加1,进程已完成访问
	  semop(semid,&op,1);//真正加1
	  exit(0);
	}
  }
}





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值