创建信号灯程序:
#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>
#define key_t double
union semun{
int val;
struct semid_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)
{
int semid,i,ret;
char path[256]="";
key_t keyvalue;
int looptime = 10000000;
strcpy(path,"/tmp");
struct tms tmsstart,tmsend;
clock_t start,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)
{
int rtn,errno;
struct sembuf p_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;
}
return 0;
}
int SemV(int id, int off)
{
int rtn,errno;
struct sembuf p_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;
}
return 0;
}
static void pr_times(clock_t real,struct tms *tmsstart,struct tms *tmsend)
{
static long clktck = 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自己进程上下文从而导致系统损耗)。