计算进程切换,此文章主要计算的是父子进程间切换100次的时间,父子进程间用管道pipe进行通信,父进程先写管道,然后进入读阻塞,子进程先进入读阻塞,然后再写管道;用管道实现父子进程的同步功能(即父进程先运行结束以后等待子进程,接着子进程运行结束以后等待父进程,父进程再运行结束以后等待子进程,子进程再运行结束以后等待父进程……如此循环往复)。实现进程间(有亲缘关系)同步,除了管道并且没有亲缘关系的进程也可以通过信号量和文件来实现,这两种方法就略略了(主要还是心懒了,感兴趣的可以随时联系一起实现,毕竟人多了有动力有心情,1+1>2)。
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/time.h>
#include <strings.h>
#include <string.h>
#include <errno.h>#define CIRCULCNT 100
#define CUNCHULEN CIRCULCNT*2int cunchu[CUNCHULEN];
struct sendmes
{
int diffusec;
struct timeval tv1;
};int main()
{
pid_t pid;
int fd1[2];
int fd2[2];
int ret,l;
for(l=0;l<CUNCHULEN;l++)
{
cunchu[l]=-1;
}
/*创建管道*/
ret=pipe(fd1);
if(ret!=0)
{
printf("%s[%d]:%d %s\n",__FUNCTION__,__LINE__,errno,strerror(errno));
return -1;
}
/*创建管道*/
ret=pipe(fd2);
if(ret!=0)
{
printf("%s[%d]:%d %s\n",__FUNCTION__,__LINE__,errno,strerror(errno));
return -1;
}
pid=fork();
if(pid==0)
{
int i=0;
struct timeval tv1;
struct timeval tv2;
struct sendmes mymes;
int difftime;
close(fd1[1]);
close(fd2[0]);
/*semid=semget((key_t)1234 ,1, IPC_CREAT|0666);
struct sembuf sem_b;*/
for(i=0;i<CIRCULCNT;i++)
{
/*bzero(&sem_b,sizeof(struct sembuf));
sem_b.sem_num=0;
sem_b.sem_op=-1;
sem_b.sem_flg=SEM_UNDO;
semop(sem_id,&sem_b,1);*//*读管道信息,并把父进程发送过来的时间读出来*/
bzero(&mymes,sizeof(struct sendmes));
read(fd1[0],&mymes,sizeof(struct sendmes));
bzero(&tv1,sizeof(struct timeval));
/*获取当前时间*/
gettimeofday(&tv1,NULL);
/*当前时间-父进程要切换的时间得出进程切换的时间,以微妙计时*/
//printf("father to son:%ld usec\n",1000000*(tv1.tv_sec-tv2.tv_sec)+tv1.tv_usec-tv2.tv_usec);
difftime=(int)(1000000*(tv1.tv_sec-mymes.tv1.tv_sec)+tv1.tv_usec-mymes.tv1.tv_usec);bzero(&mymes,sizeof(struct sendmes));
mymes.diffusec=difftime;
/*获取当前时间,并且发送给父进程*/
gettimeofday(&(mymes.tv1),NULL);
write(fd2[1],&mymes,sizeof(struct sendmes));
/*bzero(&sem_b,sizeof(struct sembuf));
sem_b.sem_num=0;
sem_b.sem_op=1;
sem_b.sem_flg=SEM_UNDO;
semop(sem_id,&sem_b,1);*/
}
close(fd1[0]);
close(fd2[1]);
return 0;
}
else
{
int i=0,j;
struct timeval tv1;
struct timeval tv2;
struct sendmes mymes;
close(fd1[0]);
close(fd2[1]);
for(i=0;i<CIRCULCNT;i++)
{
/*获取当前管道时间,并把管道时间传送给子进程*/
bzero(&mymes,sizeof(struct sendmes));
gettimeofday(&(mymes.tv1),NULL);
write(fd1[1],&mymes,sizeof(struct sendmes));
//printf("mymes.tv1.tv_sec=%ld,mymes.tv1.tv_usec=%ld\n",mymes.tv1.tv_sec,mymes.tv1.tv_usec);/*读取子进程的要切换之前的时间*/
bzero(&mymes,sizeof(struct sendmes));
read(fd2[0],&mymes,sizeof(struct sendmes));/*当前时间-子进程的要切换之前的时间得出切换时间*/
bzero(&tv2,sizeof(struct timeval));
gettimeofday(&tv2,NULL);
//printf("son to father:%ld usec\n",1000000*(tv2.tv_sec-mymes.tv1.tv_sec)+tv2.tv_usec-mymes.tv1.tv_usec);
for(j=0;j<CUNCHULEN;j++)
{
if(cunchu[j]==-1)
{
cunchu[j]=mymes.diffusec;
break;
}
}
for(j=0;j<CUNCHULEN;j++)
{
if(cunchu[j]==-1)
{
cunchu[j]=(int)(1000000*(tv2.tv_sec-mymes.tv1.tv_sec)+tv2.tv_usec-mymes.tv1.tv_usec);
break;
}
}
}
close(fd1[1]);
close(fd2[0]);
}
int j;
int maxusec=0;
int totalusec=0;
int minusec;
int secflag=0;
int cnt=0;
for(j=0;j<CUNCHULEN;j++)
{
if(-1==cunchu[j])
continue;
if(secflag==0)
minusec=cunchu[j];
secflag=1;
totalusec+=cunchu[j];
if(minusec>cunchu[j])
minusec=cunchu[j];
if(maxusec<cunchu[j])
maxusec=cunchu[j];
cnt++;
//printf("%d\n",cunchu[j]);
}
printf("cnt=%d\n",cnt);
printf("max:[%d]usec\tmin:[%d]usec\taverage:[%d]usec\n",maxusec,minusec,totalusec/cnt);
return 0;
}
线程间切换,线程切换就比进程切换容易多了,因为多个线程都是在同一个资源多种,可以实现资多线程源共享,这里用的信号量来同步多线程(同步即线程A执行完以后线程B执行,线程B执行完以后线程A执行……如此循环往复)。注意线程间同步的信号函数与进程间同步所用到的信号量函数可不一样,但是原理是一样的。
#include <stdio.h>
#include <pthread.h>
#include <errno.h>
#include <string.h>
#include <strings.h>
#include <semaphore.h>
#include <sys/time.h>#define CIRCULCNT 100
#define CUNCHULEN CIRCULCNT*2sem_t sem1;
sem_t sem2;
struct timeval tv1;
struct timeval tv2;
int cunchu[CUNCHULEN];void *func1(void *arg)
{
int i,j;
for(i=0;i<CIRCULCNT;i++)
{
/*给sem1加锁*/
sem_wait(&sem1);
bzero(&tv1,sizeof(struct timeval));
/*获取当前时间*/
gettimeofday(&tv1,NULL);
/*打印线程切换时间*/
if(i!=0)
{
//printf("func2 to func1:%ld usec\n",1000000*(tv1.tv_sec-tv2.tv_sec)+tv1.tv_usec-tv2.tv_usec);
for(j=0;j<CUNCHULEN;j++)
{
if(cunchu[j]==-1)
{
cunchu[j]=(int)(1000000*(tv1.tv_sec-tv2.tv_sec)+tv1.tv_usec-tv2.tv_usec);
break;
}
}
}
bzero(&tv1,sizeof(struct timeval));
/*获取当前时间*/
gettimeofday(&tv1,NULL);
/*给sem2解锁*/
sem_post(&sem2);
}
return NULL;
}void *func2(void *arg)
{
int i,j;
for(i=0;i<CIRCULCNT;i++)
{
/*给sem2加锁*/
sem_wait(&sem2);
bzero(&tv2,sizeof(struct timeval));
/*获取当前时间*/
gettimeofday(&tv2,NULL);
/*打印线程切换时间*/
//printf("func2 to func1:%ld usec\n",1000000*(tv1.tv_sec-tv2.tv_sec)+tv1.tv_usec-tv2.tv_usec);
for(j=0;j<CUNCHULEN;j++)
{
if(cunchu[j]==-1)
{
cunchu[j]=(int)(1000000*(tv2.tv_sec-tv1.tv_sec)+tv2.tv_usec-tv1.tv_usec);
break;
}
}
//printf("func1 to func2:%ld usec\n",1000000*(tv2.tv_sec-tv1.tv_sec)+tv2.tv_usec-tv1.tv_usec);
bzero(&tv2,sizeof(struct timeval));
/*获取当前时间*/
gettimeofday(&tv2,NULL);
/*给sem1解锁*/
sem_post(&sem1);
}return NULL;
}int main()
{
pthread_t pth1;
pthread_t pth2;
int ret;
int i;
for(i=0;i<CUNCHULEN;i++)
{
cunchu[i]=-1;
}
bzero(&tv1,sizeof(struct timeval));
bzero(&tv2,sizeof(struct timeval));
/*初始化信号量sem1*/
ret=sem_init(&sem1,0,1);
if(ret!=0)
{
printf("%s[%d]:%d %s\n",__FUNCTION__,__LINE__,errno,strerror(errno));
return -1;
}
/*初始化信号量sem2*/
ret=sem_init(&sem2,0,0);
if(ret!=0)
{
printf("%s[%d]:%d %s\n",__FUNCTION__,__LINE__,errno,strerror(errno));
return -1;
}/*创建线程pth1*/
ret=pthread_create(&pth1,NULL,func1,NULL);
if(ret!=0)
{
printf("%s[%d]:%d %s\n",__FUNCTION__,__LINE__,errno,strerror(errno));
return -1;
}
/*创建线程pth2*/
ret=pthread_create(&pth2,NULL,func2,NULL);
if(ret!=0)
{
printf("%s[%d]:%d %s\n",__FUNCTION__,__LINE__,errno,strerror(errno));
return -1;
}/*等待线程pth1*/
pthread_join(pth1,NULL);
/*等待线程pth2*/
pthread_join(pth2,NULL);/*销毁信号量sem1*/
sem_destroy(&sem1);
/*销毁信号量sem2*/
sem_destroy(&sem2);
int maxusec=0;
int minusec=0;
int cnt=0;
int totalusec=0;
int flag=0;
for(i=0;i<CUNCHULEN;i++)
{
if(cunchu[i]==-1)
continue;
if(flag==0)
minusec=cunchu[i];
totalusec+=cunchu[i];
if(maxusec<cunchu[i])
{
maxusec=cunchu[i];
}
if(minusec>cunchu[i])
{
minusec=cunchu[i];
}
cnt++;
flag=1;
//printf("%d\n",cunchu[i]);
}
printf("cnt=%d\n",cnt);
printf("max:[%d]usec\tmin:[%d]usec\taverage:[%d]usec\n",maxusec,minusec,totalusec/cnt);
return 0;
}