进程间通信 --linux篇

    linux 下进程间通信就简单多了, 可以采用信号方式.

 

    1. kill 方式

     int kill(pid_t pid,int sig), 当pid=-1 将信号广播传送给系统内所有的进程,在Redhat下测试发现, kill -1 SIGRTMIN+10, 只能广播系统关闭命令,关闭所有的用户进程; 因此此路不通,只能一个一个进程的发送信号.

    2. sigqueue 方式

    遍历所有进程, 然后发送实时信号,达到通知重装配置的目的, 代码如下: 

#include <unistd.h>
#include <dirent.h>
#include <sys/stat.h>
#include <fcntl.h>

/**
 *@brief 根据进程名查找相应PID
 * 在系统 /proc 目录下会找到各个程序运行信息,遍历即可
 *@param pName 进程名称 
 */ 
pid_t GetPidByName(const char *pName)
{
	DIR *pdir = NULL;
	struct dirent *pde = NULL;
	FILE *pf = NULL;

	char buff[128];
	pid_t pid;
	char szName[128];

	pdir = opendir("/proc");
	if (!pdir)
	{
		perror("open /proc fail.\n");
		return -1;
	}

	while ((pde = readdir(pdir)))
	{
		if ((pde->d_name[0] < '0')|| (pde->d_name[0] > '9'))
		{
			continue;
		}

		sprintf(buff, "/proc/%s/status", pde->d_name);
		pf = fopen(buff, "r");
		if (pf)
		{
			fgets(buff,sizeof(buff),pf);
			fclose(pf);

			// 文件第一行格式 Name:  top 
			sscanf(buff,"%*s %s",szName);  // sscanf不错, 获取进程名
			pid=atoi(pde->d_name);

			if(strcmp(szName,pName)==0) 
			{
				closedir(pdir);
				return pid;
			}
		}
	}

	closedir(pdir);
	return 0;
}

// 向进程发送SIGRTMIN+10 的信号 
bool SendMessage(const char *pName)
{
	if(pName==NULL)
	{
		// 无法广播非关闭信号 
		//sigqueue(-1,SIGRTMIN+10,NULL); // 实时消息

		printf("错误:没有指定进程名\n");
		return true;
	}

	pid_t pid=GetPidByName(pName);
	if(pid>0)
	{
		printf("信息:发现进程[%s:%d]\n",pName,pid);

		sigval sVal;
		sigqueue(pid,SIGRTMIN+10,sVal); // 实时信号
		return true;
	}

	printf("错误:没有发现 %s\n",pName);
	return false;
}

 

   接收信号:

/**
 *@brief 安装信号处理函数
 */
bool InstallMessage()
{
	struct sigaction act;

	sigemptyset(&act.sa_mask);
	act.sa_flags=SA_NODEFER; // 非堵塞方式
	act.sa_handler=Messge_Oper;

	// 安装信号 
	if(sigaction(SIGRTMIN+10,&act,NULL)<0)
	{
		printf("错误:安装信号失败\n");
		return false;
	}
	
	return true;
}

// 回调函数
void Message_Oper(int signo)
{
}

 

 

  3. linux下共享内存

   服务端:

/**
 *@brief 向共享内存区写入信息
 *@param szMsg 待写入字符串
 *@return 执行状态 
 */
bool WriteMsgToMemory(const char *szMsg)
{
	if(szMsg==NULL)
	{
		printf("错误:内容为空\n");
		return false;
	}

	if(!IsInitial)
	{
		if(pthread_mutex_init(&mutex,NULL)!=0)
		{
			printf("错误:初始化锁失败\n");
			return false;
		}

		// 创建一个共享内存对象并返回标识 
		if((shmid=shmget(MY_SHM_ID,SHM_SIZE,SHM_W|IPC_CREAT))<0)
		{
			perror("shmget");
			return false;
		}
	}
	
	void *mem;

	// 同步锁
	pthread_mutex_lock(&mutex);

	// 映射内存区对象
	if((mem=shmat(shmid,0,0))==(void*)-1)
		perror("shmat");

	sprintf((char*)mem,"%s",szMsg); // 写入szMsg

	shmdt(mem); // 断开共享内存连接

	pthread_mutex_unlock(&mutex);

	return true;
}

 

    客户端:

// 读取共享内存内容
bool ReadMemoryMsg(char *szMsg)
{
	int shmid;
	void *mem;

	if((shmid=shmget(MY_SHM_ID,SHM_SIZE,SHM_W|IPC_CREAT))<0)
	{
		perror("shmget");
		return false;
	}

	if((mem=shmat(shmid,0,0))==(void*)-1)
	{
		perror("shmat");
		return false;
	}

	// 读取内存
	sprintf(szMsg,"%s",(char*)mem);
	printf("信息:%s\n",szMsg);

	// 卸载映射 
	shmdt(mem) ;

	return true;
}

 

   当配置改变时,将内容写入共享内存,然后向每个进程依次发送通知信号, 进程接收到信号后, 直接读取共享内存

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值