建立號誌程式:
#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <sys/ipc.h>#include <sys/sem.h>#include <asm/errno.h>#include <errno.h>
#define key_t double
union semun{ int val; struct semid_ds *buf; ushort *array;}para;
pid_t start_process(char *prgName);
int main(int argc,char **argv){ int semid,oflags,nsems; int op_flag,id; char path[256]=""; char prgname[256]; key_t keyvalue; int i,ret; int semsem,looptime;
if(argc != 4){ printf("useage: ./semop path nsems op_flag\n"); exit(0); }
strcpy(path,argv[1]); nsems = atoi(argv[2]); op_flag = atoi(argv[3]);
printf("You Input Args is:\n"); printf("path:%s\t nsems:%d\t op_flag:%d\t\n",path,nsems,op_flag);
oflags = 0666 | IPC_CREAT | IPC_EXCL; keyvalue = ftok(path, 'S');
if(op_flag == 0){ /* Create Sem */ if((semid = semget(keyvalue,nsems,oflags))<0){ fprintf(stderr,"semget create failed!errno is %d\n",errno); exit(0); }
/* Init Sem Values */ for(i=0;i<nsems;i++){ para.val = 1; if((ret = semctl(semid,i,SETVAL,para))<0) printf("sem %d set value failed!\n",i); } printf("semop create ok!\nsemid is %d\n",semid); }
if(op_flag == 1){ if((semid = semget(keyvalue,0,0666)) < 0){ printf("semget read failed!errno is %d\n",errno); exit(-1); }
/* fork process and exec pv */ for(i=0;i<nsems;i++){ sprintf(prgname,"/home/tong/yaodl/sempv%d",i); if((ret = start_process(prgname))<0){ printf("create process failed!\n"); exit(-1); } } }
/* Del Sem */ if(op_flag == 2){ if((semid = semget(keyvalue,0,0666)) < 0){ printf("semget read failed!errno is %d\n",errno); exit(-1); } if((semctl(semid,0,IPC_RMID,0))<0){ printf("semop delete failed!semid is %d\n",semid); } else printf("semop delete ok!\nsemid is %d\n",semid); }
return 0;}
pid_t start_process(char *prgName){ pid_t pid;
switch (pid=fork()) { case 0: if (execvp(prgName, NULL) < 0) { fprintf(stderr,"Start_Process execvp error, [%s]", prgName); }
exit (0); case -1: fprintf(stderr,"Start_Process fork error, [%s]", prgName); pid = 0; break; }
return pid;}
建立成功之後,啟動多個進程去競爭。
代碼:
#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <sys/types.h>#include <sys/stat.h>#include <time.h>#include <sys/timeb.h>#include <sys/times.h>#include <fcntl.h>#include <sys/ipc.h>#include <sys/sem.h>#include <asm/errno.h>#include <errno.h>#definekey_tdoubleunion semun{intval;structsemid_ds *buf;ushort*array;}para;int SemP(int id, int off,int flag);int SemV(int id, int off);static void pr_times(clock_t real,struct tms *tmsstart,struct tms *tmsend);int main(int argc,char **argv){intsemid,i,ret;charpath[256]="";key_tkeyvalue;int looptime = 10000000;strcpy(path,"/tmp");struct tmstmsstart,tmsend;clock_tstart,end;keyvalue = ftok(path, 'S');/* PV opration */if((semid = semget(keyvalue,0,0666)) < 0){printf("semget read failed!errno is %d\n",errno);exit(-1);}if((start = times(&tmsstart)) == -1){printf("starting time failed!\n");exit(-1);}for(i=0;i<looptime;i++){if(SemP(semid,0,1) < 0){printf("SemP failed!i=%d\n",i);exit(-1);}if(SemV(semid,0) < 0){printf("SemV failed!i=%d\n",i);exit(-1);}}if((end = times(&tmsend)) == -1){printf("ending time failed!\n");exit(-1);}pr_times(end-start,&tmsstart,&tmsend);return 0;}int SemP(int id, int off, int flag){intrtn,errno;struct sembufp_buf;p_buf.sem_num = off;p_buf.sem_op = -1;if (flag)p_buf.sem_flg = SEM_UNDO;while(1){rtn=semop(id, &p_buf, 1);if( rtn < 0 ){if( errno == EINTR ) continue;else return -1;}break;}return0;}int SemV(int id, int off){intrtn,errno;struct sembufp_buf;p_buf.sem_num = off;p_buf.sem_op = 1;p_buf.sem_flg = SEM_UNDO;while(1){rtn=semop(id, &p_buf, 1);if( rtn < 0 ){if( errno == EINTR ) continue;else return -1;}break;}return0;}static void pr_times(clock_t real,struct tms *tmsstart,struct tms *tmsend){staticlongclktck = 0;if(clktck == 0){if((clktck = sysconf(_SC_CLK_TCK)) < 0){printf("sysconf error!\n");exit(-1);}}fprintf(stderr,"sempv0");fprintf(stderr,"real:%7.2f\n",real/(double)clktck);fprintf(stderr,"user:%7.2f\n",(tmsend->tms_utime - tmsstart->tms_utime)/(double)clktck);fprintf(stderr,"sys:%7.2f\n",(tmsend->tms_stime - tmsstart->tms_stime)/(double)clktck);}
本次測試的目的是為了驗證,在父進程fork多個子進程後,多個子進程之間的pv競爭會不會導致系統額外的開銷。
(因為子進程會共用父進程的進程空間、環境變數等,驗證每個子進程執行的時候會不會重新load自己進程上下文從而導致系統損耗)。