Linux----进程间的通信

进程间通信之信号:
    信号 -- 软中断 
    中断 
         信号 --- 中断源 
         中断(信号)处理程序 --- 负责对该中断(信号)做出反应的 

//信号处理函数 的注册函数  
    #include

       typedef void (*sighandler_t)(int);

       sighandler_t signal(int signum, sighandler_t handler);

       功能:
           给signum信号设置一个信号处理函数 
       参数:
         @signum   要处理的信号 
         @handler  信号处理函数 
       返回值:
         成功 将返回上一次的信号处理函数的地址 
         失败  SIG_ERR   (void (*sighandler_t)(int) 类型的 -1)

void sighandler (int signo) //信号处理函数 
    {    
        
    }
    //signo  //参数 ---表示 接收到的信号的编号
   
   SIGKILL 
   SIGSTOP  //不能阻塞,不能处理,不能忽略

#include
#include
#include

typedef void (*sighandler_t)(int);

void sighandler(int signo)
{
	printf("signo = %d\n",signo);
}

int main(int argc, const char *argv[])
{
	//signal(SIGINT,SIG_IGN);
	sighandler_t ret = signal(SIGINT,sighandler);
	printf("ret = %p\n",ret);
	printf("ret = %p\n",SIG_IGN);

	while(1)
	{
		printf("hello \n");
		sleep(1);
	}

	//signal(SIGINT,ret);
	return 0;
}

1、发送端
    #include
    #include

    int   kill(pid_t pid, int sig);
    功能:通过该函数可以给pid进程发送信号为sig的系统信号。
    参数:pid 要接收信号的进程pid
          sig 当前程序要发送的信号编号 《=== kill  -l
    返回值:成功 0
            失败  -1;

练习:
        编写一个自己的kill程序,尽量模拟kill命令的效果。

#include
#include
#include
#include

int main(int argc, const char *argv[])
{
	pid_t pid = atoi(argv[1]);

	int i = 0;
	for(i = 1;i<32;++i)
	{
		printf("i =%d\n",i);
		if(kill(pid,i)<0)
		{
			perror("kill fail");
			return -1;
		}
	}
	return 0;
}

unsigned int alarm(unsigned int seconds);SIGALAM
    功能:定时由系统给当前进程发送信号
          也称为闹钟函数

          闹钟只有一个,定时只有一次有效,
          但是必须根据代码逻辑是否执行判断。


    int pause(void);
    功能:
         进程暂停,不再继续执行,除非
          收到其他信号。  
    

    练习:
      

         检测用户是否输入,
       如果用户3s没有输入,
       则超时一次,
       如果超时3次自动退出
 

#include
#include
#include
#include
#include

int cnt = 0;
void sighandler(int signo)
{
	alarm(3);
	cnt++;
	printf("cnt=%d\n",cnt);
	if(cnt==3)
	{
		exit(0);
	}
}


int main(int argc, const char *argv[])
{
	alarm(3);
	char buf[1024];
	signal(SIGALRM,sighandler);
	while(1)
	{
		fgets(buf,sizeof(buf),stdin);
		printf("buf = %s\n",buf);
	alarm(3);
	cnt = 0;
	}
	return 0;
}

传统的进程间通信方式:
1.无名管道
2.有名管道
3.信号 

Sys V  系统v的IPC对象:
1.共享内存 (*)  --- 效率最高的通信方式
2.消息队列  //--- 系统提供一种消息队列的通信机制 
3.信号量集  //--- 信号量集(集合)---很多个信号量 
                    //互斥 和 同步 

共享内存:
    是一块内核中保留的物理内存空间 

/IPC对象共享内存:
1.ftok
  ftok()创建临时键值。
    #include
    #include
                "/etc"                        '!'
    key_t ftok(const char *pathname, int proj_id);
    功能:通过该函数可以将pathname指定的路径用来以
          proj_id生成唯一的临时键值。
    参数:pathname 路径+名称===》任意文件,只要不会
          被删除重建即可。
          proj_id  整形的数字,一般用ASCII码的单字符
          表示与参数1的运算。

    返回值:成功 返回唯一键值
            失败  -1;

2.shmget //获取IPC对象 
 // shared memory                     
                  
1、IPC_PRIVATE 固定的私有键值,其值等于 0x0
        一般用于有亲缘关系的进程间使用。       
    
    
1、申请对象:shmget()
    #include
    #include
    ps aux|grep a.out
        shared memory get         IPC_CREAT|0666
    int shmget(key_t key, size_t size, int shmflg);
    功能:
         使用唯一键值key向内核提出共享内存使用申请
    参数:key   唯一键值
          size  要申请的共享内存大小
          shmflg 申请的共享内存访问权限,八进制表示
          如果是第一个申请,则用IPC_CREAT
          如果要检测是否存在,用IPC_EXCL
    返回值:
            成功 返回共享内存id,一般用shmid表示
            失败  -1;

            share memory attach
            
            
    key --- IPC_PRIVATE //创建一个key对应ipc对象  ---- 主要用于亲缘关系进程间 
    key --- 不是IPC_PRIVATE  
            shmflag 指定 IPC_CREAT|0666 //此时如果ipc对象不存在,则创建
            
    ipcs  -a 查询共享内存,信号量集,消息队列
    ipcrm -s 删除信号量集
          -m 删除共享内存
          
3.建立映射 
  shmat 
  映射对象:shmat()
    void *shmat(int shmid, const void *shmaddr, int shmflg);
    功能:将指定shmid对应的共享内存映射到本地内存。
    参数:shmid 要映射的本地内存
          shmaddr 本地可用的地址,如果不确定则用NULL,表示
                  由系统自动分配。
          shmflg  
          0         ,  表示读写
          SHM_RDONLY, 只读
    返回值:
           成功 返回映射的地址,一般等于shmaddr
            失败 (void*)-1

4. 撤销映射:shmdt
    int shmdt(const void *shmaddr);
    功能:将本地内存与共享内存断开映射关系。
    参数:shmaddr 要断开的映射地址。
    返回值:成功  0
            失败  -1;
5. 删除对象:shmctl
    int shmctl(int shmid, int cmd, struct shmid_ds *buf);
    功能:
         修改共享内存属性,也可以删除指定的共享内存对象。
    参数:shmid 要删除的共享内存对象
          cmd 
               IPC_RMID 删除对象的宏
          buff  NULL 表示只删除对象。
    返回值:成功 0
            失败 -1
 

#include
#include
#include
#include

int main(int argc, const char *argv[])
{
	//1.key
	key_t key = ftok("/",'B');

	if(key<0)
	{
		perror("fork fail");
		return -1;
	}

	printf("key is %#x\n",key);

	//2.shmid
	int shmid = shmget(key,1024,IPC_CREAT|0666);

	if(shmid<0)
	{
		perror("shmget fail");
		return -1;
	}
	printf("shmid = %d\n",shmid);

	//shmat
	void *p = shmat(shmid,NULL,0);

	if(p==NULL)
	{
		perror("shmat fail");
		return -1;
	}

	int i = 0;
	while(i < 10)
	{
	*(int*)p = 100;
	i++;
	printf("i = %d\n",i);
	sleep(1);
	}

	//shmdt
	if(shmdt(p)<0)
	{
		perror("shmdt fail");
		return -1;
	}
	
	//5.shmctl
	if(shmctl(shmid,IPC_RMID,NULL)<0)
	{
		perror("shmctl fail");
		return -1;
	}

	return 0;
}
#include
#include
#include
#include

int main(int argc, const char *argv[])
{
	//1.key
	key_t key = ftok("/",'B');

	if(key<0)
	{
		perror("fork fail");
		return -1;
	}

	printf("key is %#x\n",key);

	//2.shmid
	int shmid = shmget(key,1024,IPC_CREAT|0666);

	if(shmid<0)
	{
		perror("shmget fail");
		return -1;
	}
	printf("shmid = %d\n",shmid);

	//shmat
	void *p = shmat(shmid,NULL,0);

	if(p==NULL)
	{
		perror("shmat fail");
		return -1;
	}

	printf("%d\n",*(int *)p);

	//shmdt
	if(shmdt(p)<0)
	{
		perror("shmdt fail");
		return -1;
	}
	
	//5.shmctl
	if(shmctl(shmid,IPC_RMID,NULL)<0)
	{
		perror("shmctl fail");
		return -1;
	}

	return 0;
}

 kill(pid,SIGUSR1)
 pause 

#include
#include
#include

typedef void (*sighandler_t)(int);

void sighandler(int signo)
{
	printf("signo = %d\n",signo);
}

int main(int argc, const char *argv[])
{
	
	sighandler_t ret = signal(SIGINT,sighandler);

	while(1)
	{
		printf("hello \n");
		pause();
	}

	//signal(SIGINT,ret);
	return 0;
}

你可能感兴趣的:(linux,运维,服务器)