[多核并行计算]进程间通信(三)套接字

socket套接字不仅可以在不同主机间通信,如TCP/UDP等网络方式通信。也可以再本机为不同进程间通信提供服务。

int socket(int domain, int type, int protocol);

socket函数接口中有3个参数,其中第一个domain参数决定了通信域,如果是本机内通信传入AF_UNIX, AF_LOCAL,如果是跨主机使用ip进行通信则传入AF_INET等。

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h> 
#include <math.h> 
#include <sys/time.h> 
#include <sys/stat.h>
#include <errno.h>
#include <string.h>
#include <math.h>
#include <pthread.h>
#include <sys/wait.h>
#include <sys/mman.h>
#include <sys/resource.h>
#include <sys/select.h>
#include <sys/epoll.h>

#include<sys/socket.h>
#include<sys/un.h>
#define UNIX_DOMAIN "/home/tmp/UNIX.domain"
 
void set_thread_affinity(int cpuid);
int set_sc(int type,int prority);
void rtclock_gettime(unsigned long long *tt);
int allocate_rtcore();
int release_rtcore();
int smp_comm1();

#define PRINT_NS		1
#define SEND_ONLY		0
#define RT_MODE_ENABLE		1
#define MAX_PROCESSER_NUM	1024
#define MSG_SIZE		(1024*8)
struct Process
{
	int     id;
	pid_t	pid;
	
}process;

struct Process *processes;
int nr_process = 4;
int shm_fd;
int epoll_fd;
int myid = 0;
static pthread_barrier_t *barrier;
static char *shm_buffer;
 
#define SHARE_RFIFO_PATH "/home/tmp/_fifo"
#define SHARE_WFIFO_PATH "/home/tmp/_fifo"
#define F 2.2E3
#define COMM_NUM 24
 
int    on_cpu;
double dval = 1.23;
double sendbuf[4096];
double recvbuf[4096];
int sendfd[MAX_PROCESSER_NUM];
int recvfd[MAX_PROCESSER_NUM];
static int testloop = 8000;
static int calcloop = 20;
static int cpu_freq = 0;

/*
   1. all processes use a same share memory
   2. The memory area is divided into several sub-blocks
   3. each process use two sub-blocks, one for read and another for write.

                         (Four process IPC)
                   --------              --------
                  |        | ---------> |        |
                  |process0| <--------- |process1|
                  |        |            |        |
                   --------              --------
                   /| |     |\\      //|   | |\
                    | |       \\    //     | |
                    | |        \\  //      | |
                    | |         \\//       | |
                    | |          *         | |
                    | |         //\\       | |
                    | |        //  \\      | |
                    | |       //    \\     | |
                    | |/    |//      \\|  \| |
                   --------              --------
                  |        |            |        |
                  |process2| ---------> |process3|
                  |        | <--------- |        |
                   --------             --------

                                 shared memory range(4 process)
 -----------------------------------------------------------------------------------------------
|       |       |       |       |       |       |       |       |       |       |       |       |
|  0-1  |  0-2  |  0-3  |  1-0  |  1-2  |  1-3  |  2-0  |  2-1  |  2-3  |  3-0  |  3-1  |  3-2  |
|       |       |       |       |       |       |       |       |       |       |       |       |
`-----------------------------------------------------------------------------------------------
*/

void delay(int loop)
{
	int i,j;
	for(i=0; i<loop;i++)
		for(j=0; j<100000; j++)
			dval = sin(3.1415926 + 0.5*dval);
}
int do_calc(int loop)
{
        int i,j;
        for(i=0; i<loop; i++) {
		for(j=0; j<COMM_NUM; j++) {
			sendbuf[j] += sin(recvbuf[j]*3.1415926 + 0.5*myid);
		}                
        }
}

int process_barrier(char *barrier)
{
	char *p = barrier;
	int i,sum = 0;
	int id = myid;
	unsigned int count=0;
	static int flag = 1;

	p[id] = flag;
	while(sum != nr_process){
		sum = 0;
		for(i=0; i<nr_process; i++) {
			if(p[i] == flag)
				sum++;
		}
		count++;
	}
	flag = flag ? 0 : 1;
	//printf("child%d: barrier num %d\n", myid, count);
	return 0;
}

int do_simulation(int loop_num, int one_loop_num)
{
        int i, count = 0, ret = 0;
        struct timeval tv1, tv2;
	unsigned long long t1,t2,t3,t4,t5,t6;
        unsigned long long us1, us2, ms1, ms2;
        unsigned long long ms, us;
	unsigned long long val, cal, sum_cal, sum_val, avg_cal, avg_val;
	unsigned long long tmax_val=0, tmin_val=100000000,tmax_cal=0,tmin_cal=100000000;
	int skip = 0, warm = 10;

	sum_cal = 0;
	sum_val = 0;
        for(i=1; i<=loop_num; i++) {
		
		ret = process_barrier((char*)barrier);
		if(ret != 0 && ret != PTHREAD_BARRIER_SERIAL_THREAD) {
			printf("process%d pid[%d]: barrier_wait error! %s\n", myid, process.pid, strerror(errno));
			return -1;
		}

		rtclock_gettime(&t1);
		skip = smp_comm1();
		rtclock_gettime(&t2);
                do_calc(one_loop_num);
		rtclock_gettime(&t3);
				
		if(skip)
			continue;
                if(i > warm) {
			val = (t3 - t1)/1000;
			if(val > tmax_val) {
				tmax_val = val;
			}
			if(val < tmin_val) {
				tmin_val = val;
			}

			cal = (t3 - t2)/1000;
			if(cal > tmax_cal) {
				tmax_cal = cal;
			}
			if(cal < tmin_cal) {
				tmin_cal = cal;
			}
			sum_val += val;
			sum_cal += cal;
			count++;
                }
        }
	avg_val = sum_val/(loop_num-warm);
	avg_cal = sum_cal/(loop_num-warm);
#if 0
	tmax_val /= F;tmin_val /= F;avg_val /= F;
	tmax_cal /= F;tmin_cal /= F;avg_cal /= F;
#endif
        printf("CPU %d Jitter %llu mean %llu max %llu min %llu | CALC: J %llu mean %llu max %llu min %llu\n", \
                        myid+1,  tmax_val-avg_val, avg_val, tmax_val, tmin_val,\
			tmax_cal-avg_cal, avg_cal, tmax_cal, tmin_cal);
	
	process_barrier((char*)barrier);
	if(cpu_freq)
		printf("CPU %d Jitter %.6f mean %.6f\n", \
			myid+1, (float)(tmax_val-avg_val)/cpu_freq,(float)(avg_val)/cpu_freq);
	return 0;
}

void *process_func(void *args)
{
	int ret;
	int loop = 1;
	char buf[4096];
	
	set_thread_affinity(myid+1);
	sleep(1);
	set_sc(0,90);
	
#if RT_MODE_ENABLE
	allocate_rtcore();
#endif
	do_simulation(testloop, calcloop);

#if RT_MODE_ENABLE
	release_rtcore();
#endif

err:
	exit(ret);
}

void print_shm()
{
	int i,j,k;
	int idx=0;
	char *p;
	for(i=0; i<nr_process; i++) {
		for(j=0; j<nr_process; j++) {
			if(i == j)
				continue;
			printf("[%d-%d]: ",i,j);
		
			p = shm_buffer+(idx*MSG_SIZE);
			for(k=0; k<MSG_SIZE; k++)
				printf(" %d", p[k]);
			printf("\n");
			idx++;
		}
	}
}

int get_shm_idx(int send_id, int recv_id)
{
	int i,j;
	int idx = 0;
	int tmp;

	for(i=0; i<nr_process; i++) {
		for(j=0; j<nr_process; j++) {
			if(i == j)
				continue;
			if(send_id == i && recv_id == j)
				return idx;
			idx++;
		}
	}
	
	return idx;
}

char* get_shm_offset(int send_id, int recv_id)
{
	int idx = 0;

	idx = get_shm_idx(send_id, recv_id);
	if(idx == nr_process*(nr_process-1))
		printf("child%d: cannot find shm !\n", myid);
	return shm_buffer + idx*MSG_SIZE;
}

int smp_recv()
{
	int i,j,k,n,sum = 0;
	char *p;
	char buf[MSG_SIZE];
	int flag[256] = {0};

	for(i=0; i<nr_process; i++) {
		if(i == myid)
			continue;
		if(read(recvfd[i], (char*)recvbuf, sizeof(recvbuf)) < 0) {
			perror("[smp_recv]: read error");
		}
		sum++;
	}
	if(sum != nr_process-1)
		printf("child%d: smp_recv sum != nr_process-1\n", myid);
	return 0;
}

int smp_send()
{
	int i, j,wlen, rlen;
	char *p, *buf;
	
	wlen = MSG_SIZE;
	rlen = MSG_SIZE;
	for(i=0; i<nr_process; i++) {
		if(i == myid)
			continue;

		if(write(sendfd[i], (char*)sendbuf, MSG_SIZE) < 0)
			perror("[smp_send]: write error");
	}
	return 0;
}

int smp_comm1()
{
	static int i = 0;
	static int n = sizeof(recvbuf)/MSG_SIZE;
	smp_send();
#if SEND_ONLY
	if(++i == n) {
		i = 0;
		smp_recv();
		return 1;
	}
#else
	smp_recv();
#endif
	//printf("[%d] %s %d count=%d\n", process.pid,__func__,__LINE__, ++i);
	return 0;
}

 
int barrier_init()
{
	int oflag = 0;
	pthread_barrierattr_t ba;
	int pshared = PTHREAD_PROCESS_SHARED;
	
	char shm_name[] = "tmp_process_barrier";

	/* Initialize a barrier attributes object */
	if (pthread_barrierattr_init(&ba) != 0) {
		printf("Error at pthread_barrierattr_init()\n");
		return -1;
	}
	/* Set the pshard value to private to shared */
	if (pthread_barrierattr_setpshared(&ba, pshared) != 0) {
		printf("Error at pthread_barrierattr_setpshared()\n");
		return -1;
	}
	/* Create shared object */
	if(myid == 0) {
		shm_unlink(shm_name);
		oflag = O_RDWR | O_CREAT | O_EXCL;
	}else{
		oflag = O_RDWR | O_EXCL;
		delay(10);
		//usleep(100000);
	}
	shm_fd = shm_open(shm_name, oflag, S_IRUSR | S_IWUSR);
	if (shm_fd == -1) {
		perror("Error at shm_open()");
		return -1;
	}
	if (ftruncate(shm_fd, sizeof(pthread_barrier_t)+nr_process) != 0) {
		perror("Error at ftruncate()");
		shm_unlink(shm_name);
		return -1;
	}
	/* Map the shared memory object to my memory */
	barrier = mmap(NULL, sizeof(pthread_barrier_t)+nr_process, PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, 0);
	if (barrier == MAP_FAILED) {
		perror("Error at first mmap()");
		shm_unlink(shm_name);
		return -1;
	}
	if(myid == 0) {
	/* Initialize a barrier */
	if ((pthread_barrier_init(barrier, &ba, nr_process)) != 0) {
		printf("Error at pthread_barrier_init()\n");
		return -1;
	}
	char *p = (char*)barrier;
	p[myid] = 0;
	memset(p, 0, sizeof(pthread_barrier_t)+nr_process);
	}
	/* Cleanup */
	if ((pthread_barrierattr_destroy(&ba)) != 0) {
		printf("Error at pthread_barrierattr_destroy()\n");
		return -1;
	}
	return 0;	
}

int shm_init()
{
	int shm_fd;
	int oflag;
	int shm_size = (nr_process*(nr_process-1))*MSG_SIZE;
	char shm_name[] = "tmp_process_shm";

	if(myid == 0) {
		shm_unlink(shm_name);
		oflag = O_RDWR | O_CREAT | O_EXCL;
		shm_fd = shm_open(shm_name, oflag, S_IRUSR | S_IWUSR);
		if (shm_fd == -1) {
			perror("Error at shm_open()");
			return -1;
		}
		if (ftruncate(shm_fd, shm_size) != 0) {
			perror("Error at ftruncate()");
			shm_unlink(shm_name);
			return -1;
		}
	}else{
		delay(10);
		oflag = O_RDWR | O_EXCL;
		shm_fd = shm_open(shm_name, oflag, S_IRUSR | S_IWUSR);
		if (shm_fd == -1) {
			perror("Error at shm_open()");
			return -1;
		}

	}
	/* Map the shared memory object to my memory */
	shm_buffer = mmap(NULL, shm_size, PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, 0);
	if (shm_buffer == MAP_FAILED) {
		perror("Error at first mmap()");
		shm_unlink(shm_name);
		return -1;
	}
	//close(shm_fd);
	if(myid == 0) {
		memset(shm_buffer, 0, shm_size);
	}else {
		delay(40);
	}
	return 0;
}

void *thread_emt(__attribute__((unused)) void *arg)
{
	process_func(arg);
}
 
int socket_init()
{
	struct sockaddr_un clt_addr;
	struct sockaddr_un srv_addr;
	struct sockaddr_un conn_addr;
	socklen_t clt_addr_len;
    
	int listen_fd[MAX_PROCESSER_NUM];
	int conn_fd[MAX_PROCESSER_NUM];
	int i, ret;
	char rpath[512];
	char wpath[512];
	int len;
	for(i=0; i<nr_process; i++) {
		if(i == myid)
			continue;
		listen_fd[i] = socket(AF_UNIX, SOCK_STREAM, 0);
		if(listen_fd[i] < 0) {
			printf("child%d socket create error! %s\n", myid, strerror(errno));
			exit(-1);
		}
		conn_fd[i] = socket(AF_UNIX, SOCK_STREAM, 0);
		if(conn_fd[i] < 0) {
			printf("child%d socket create error! %s\n", myid, strerror(errno));
			exit(-1);
		}
		len = 1;
		if(setsockopt(listen_fd[i], SOL_SOCKET, SO_REUSEADDR, &len, sizeof(len)) < 0) {
			printf("child%d setsockopt SO_REUSEADDR error! %s\n", myid, strerror(errno));
			exit(-1);
		}
		sprintf(rpath, "%s%d_%d", UNIX_DOMAIN, myid, i);
		sprintf(wpath, "%s%d_%d", UNIX_DOMAIN, i, myid);
		strncpy(srv_addr.sun_path, rpath, sizeof(srv_addr.sun_path)-1);
		strncpy(conn_addr.sun_path, wpath, sizeof(conn_addr.sun_path)-1);
		srv_addr.sun_family = AF_UNIX;
		conn_addr.sun_family = AF_UNIX;
		ret = bind(listen_fd[i], (struct sockaddr*)&srv_addr, sizeof(srv_addr));
		if(ret < 0) {
			printf("child%d socket bind error! %s\n", myid, strerror(errno));
			exit(-1);
		}
		ret = listen(listen_fd[i], 1);
		if(ret < 0) {
			printf("child%d socket listen error! %s\n", myid, strerror(errno));
			exit(-1);
		}
	}
	for(i=0; i<nr_process; i++) {
		if(i == myid)
			continue;
		sprintf(rpath, "%s%d_%d", UNIX_DOMAIN, myid, i);
		sprintf(wpath, "%s%d_%d", UNIX_DOMAIN, i, myid);
		strncpy(srv_addr.sun_path, rpath, sizeof(srv_addr.sun_path)-1);
		strncpy(conn_addr.sun_path, wpath, sizeof(conn_addr.sun_path)-1);
		srv_addr.sun_family = AF_UNIX;
		conn_addr.sun_family = AF_UNIX;
		if(i > myid) {
			len = sizeof(clt_addr);
			recvfd[i] = accept(listen_fd[i], (struct sockaddr*)&clt_addr, &len);
			if(recvfd[i] < 0) {
				printf("child%d socket accept error! %s\n", myid, strerror(errno));
				exit(-1);
			}
			usleep(10*1000);
			ret = connect(conn_fd[i], (struct sockaddr*)&conn_addr,sizeof(conn_addr));
			if(ret < 0) {
				printf("child%d connect error! %s\n", myid, strerror(errno));
				exit(-1);
			}
			sendfd[i] = conn_fd[i];
		} else {
			usleep(10*1000);
			ret = connect(conn_fd[i], (struct sockaddr*)&conn_addr,sizeof(conn_addr));
			if(ret < 0) {
				printf("child%d connect error! %s\n", myid, strerror(errno));
				exit(-1);
			}
			sendfd[i] = conn_fd[i];
			len = sizeof(clt_addr);
			recvfd[i] = accept(listen_fd[i], (struct sockaddr*)&clt_addr, &len);
			if(recvfd[i] < 0) {
				printf("child%d socket accept error! %s\n", myid, strerror(errno));
				exit(-1);
			}
		}
	}
	return 0;
}

int main(int argc, char **argv)
{
        int i, ret = 0;
        int rfd, wfd;
	int cpu_num;
	struct Process *p;
	
	if(argc > 1) {
		myid = atoi(argv[1]);
	}
	if(argc > 2) {
		cpu_num = sysconf(_SC_NPROCESSORS_ONLN);
		nr_process = atoi(argv[2]);
		if(nr_process > cpu_num-2) {
			printf("max process is %d!\n", cpu_num-2);
			return -1;
		}
	}
	if(argc > 3) {
		testloop = atoi(argv[3]);
	}
	if(argc > 4) {
		calcloop = atoi(argv[4]);
	}
	if(argc > 5) {
		cpu_freq = atoi(argv[5]) / 1000; /* GHz */
	}
	process.id = myid;
	process.pid = getpid();
	printf("child%d: pid %d, nr_process %d, testloop %d calcloop %d\n",\
		 myid,getpid(), nr_process, testloop, calcloop);

	struct rlimit rlimit_new;
	rlimit_new.rlim_cur = RLIM_INFINITY;
	rlimit_new.rlim_max = RLIM_INFINITY;
	if(setrlimit(RLIMIT_MEMLOCK, &rlimit_new) != 0) {
		printf("setrlimit error ,exit\n");
		exit(1);
	}
	if(mlockall(MCL_CURRENT|MCL_FUTURE) !=0) {
		printf("lock memeory error ,exit\n");
		exit(1);
	}
	if(barrier_init() < 0) {
		printf("barrier_init error ,exit\n");
		exit(1);
	}
	if(socket_init() < 0) {
		printf("socket_init error ,exit\n");
		exit(1);
	}

	memset(sendbuf, myid+1, sizeof(sendbuf));
	memset(recvbuf, myid+2, sizeof(recvbuf));
	ret = process_barrier((char*)barrier);
	if(ret != 0 && ret != PTHREAD_BARRIER_SERIAL_THREAD) {
		printf("process%d pid[%d]: barrier_wait error! %s\n", myid, process.pid, strerror(errno));
		goto err;
	}

	process_func(&process);

	ret = process_barrier((char*)barrier);
	if(ret != 0 && ret != PTHREAD_BARRIER_SERIAL_THREAD) {
		printf("process%d pid[%d]: barrier_wait error! %s\n", myid, process.pid, strerror(errno));
		goto err;
	}
	munlockall();
	
	return 0;
err:
	return -1;
}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值