[多核并行计算]进程间通信(二)共享内存

先把代码贴上,后面在做讲解。。

#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>

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 SEND_ONLY		0
#define RT_MODE_ENABLE		1
#define MAX_PROCESS_NUM		64
#define MSG_SIZE		24
struct Process
{
	int     id;
	pid_t	pid;
	
}process;

struct Process *processes;
int nr_process = 4;
int shm_fd;
int epoll_fd;
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
 
int    on_cpu;
double dval = 1.23;
double	sendbuf[4096];
double recvbuf[4096];
static int testloop = 8000;
static int calcloop = 50;

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<nr_process; j++) {
			dval = sin(recvbuf[j]*3.1415926 + 0.5);
			sendbuf[i%sizeof(sendbuf)] += dval;
		}                
        }
}

int process_barrier(char *barrier)
{
	char *p = barrier;
	int i,sum = 0;
	int id = process.id;
	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", process.id, 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", process.id, process.pid, strerror(errno));
			return -1;
		}

		rtclock_gettime(&t1);
		if(i % 5000 == 0) {
			//printf("[%d]: t1 %llu, t2 %llu, t3 %llu\n", process.pid,t1,t2,t3);
		}
		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("on cpu %d count %d, Jitter %llu, mean %llu max %llu, min %llu | CALC: J %llu mean %llu max %llu min %llu\n", \
                        process.id+1, count, tmax_val-avg_val, avg_val, tmax_val, tmin_val,\
			tmax_cal-avg_cal, avg_cal, tmax_cal, tmin_cal);
	return 0;
}

void *process_func(void *args)
{
	int ret;
	int loop = 1;
	char buf[4096];
	
	set_thread_affinity(process.id+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", process.id);
	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};

	while(sum != nr_process-1) {
		for(i=0; i<nr_process; i++) {
			if(i == process.id)
				continue;
			if(flag[i] == 1)
				continue;
			n = 0;
			p = get_shm_offset(i, process.id);
			for(j=0; j<MSG_SIZE; j++) {
				n += p[j];
			}
			if(n == MSG_SIZE) {
				flag[i] = 1;
				sum++;
				for(k=0; k<MSG_SIZE; k++)
					p[k] = 0;
			}
		}
	}
	if(sum != nr_process-1)
		printf("child%d: smp_recv sum != nr_process-1\n", process.id);
	return 0;
}

int smp_send()
{
	int i, j,wlen, rlen;
	char *p;
	
	wlen = MSG_SIZE;
	rlen = MSG_SIZE;
	for(i=0; i<nr_process; i++) {
		if(i == process.id)
			continue;
		p = get_shm_offset(process.id, i);
		memset(p, 1, MSG_SIZE);
	}
	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(process.id == 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(process.id == 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[process.id] = 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(process.id == 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(process.id == 0) {
		memset(shm_buffer, 0, shm_size);
	}else {
		delay(40);
	}
	return 0;
}

void *thread_emt(__attribute__((unused)) void *arg)
{
	process_func(arg);
}

int main(int argc, char **argv)
{
        int i, ret = 0;
        int rfd, wfd;
	int myid = 0;
	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]);
	}
	process.id = myid;
	process.pid = getpid();
	printf("child%d: pid %d, nr_process %d, testloop %d\n", myid,getpid(), nr_process, testloop);

	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(shm_init() < 0) {
		printf("shm_init error ,exit\n");
		exit(1);
	}

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

猜你喜欢

转载自blog.csdn.net/y33988979/article/details/82705457