进程与线程——Linux进程与线程通讯

实验一 进程与线程——Linux进程与线程通讯

一、实验目的

深刻理解线程和进程的概念,掌握线程与进程在组成成分上的差别,以及与其相适应的通讯方式和应用目标。

二、实验内容

1、以Linux系统进程和线程机制为背景,掌握fork()和clone()系统调用的形式和功能,以及与其相适应的高级通讯方式。由fork派生的子进程之间通过pipe通讯,由clone创建的线程之间通过共享内存通讯,对于后者需要考虑互斥问题。

2、以生产者/消费者问题为例,通过实验理解fork()和clone()两个系统调用的区别。程序要求能够创建4个进程或线程,其中包括两个生产者和两个消费者,生产者和消费者之间能够传递数据。

原书中代码 不再给出:遇到问题如下

1.书中有打印错误  CLONE_SIGNAND 应为 CLONE_SIGHAND

2.在mian中,创建线程的代码段;书中有错误;

int clone_flag,arg,retval;
	char *stack;03.
	clone_flag = CLONE_VM|CLONE_SIGNAND|CLONE_FS|CLONE_FILES;
	int i;
	for(i=0;i<2;i++)
	{
		arg=i;
		stack=(char*)malloc(4096);
		retval = clone((void*)producer,&(stack[4095]),clone_flag,(void*)&arg);
		stack=(char*)malloc(4096);
		retval = clone((void*)consumer,&(stack[4095]),clone_flag,(void*)&arg);
	}


分析:
声明变量 *arg,在循环中 把 arg=i; 调用 clone时, 传入参数 &arg;

虽然 arg每次循环后 ,值不一样,但是 传入的参数&arg 即arg的地址没有变化,所以 作者原意 要创建两个 生产者和两个消费者的线程, 在实际运行会发现 结果只能创建出一个生产者和一个消费者。

修改后代码为:

int clone_flag,*arg, args[2] = {0, 1},retval;
	char *stack;
	clone_flag = CLONE_VM|CLONE_SIGHAND|CLONE_FS|CLONE_FILES;
	int i;
	for(i=0;i<2;i++)
	{
		arg = &args[i];
		stack=(char*)malloc(4096);
		retval = clone((void*)producer,&(stack[4095]),clone_flag,(void*)arg);
		stack=(char*)malloc(4096);
		retval = clone((void*)consumer,&(stack[4095]),clone_flag,(void*)arg);
	}


完整代码如下:

#include "sched.h"
#include "pthread.h"
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "semaphore.h"
 
int producer(void *args);
int consumer(void *args);
pthread_mutex_t mutex;
sem_t product;
sem_t warehouse;

char buffer[8][4];
int bp=0;

int main(int argc,char **argv)
{
	pthread_mutex_init(&mutex,NULL);
	sem_init(&product,0,0);
	sem_init(&warehouse,0,8);
	int clone_flag,*arg, args[2] = {0, 1},retval;
	char *stack;
	clone_flag = CLONE_VM|CLONE_SIGHAND|CLONE_FS|CLONE_FILES;
	int i;
	for(i=0;i<2;i++)
	{
		arg = &args[i];
		stack=(char*)malloc(4096);
		retval = clone((void*)producer,&(stack[4095]),clone_flag,(void*)arg);
		stack=(char*)malloc(4096);
		retval = clone((void*)consumer,&(stack[4095]),clone_flag,(void*)arg);
	}
	exit(1);
}

int producer(void *args)
{
	int id=*((int*)args);
	int i;
	for(i=0;i<10;i++)
	{
		sleep(i+1);
		sem_wait(&warehouse);
		pthread_mutex_lock(&mutex);
		if(id==0)
			strcpy(buffer[bp],"aaa\0");
		else
			strcpy(buffer[bp],"bbb\0");
		bp++;
		printf("producer %d produce %s in %d\n",id,buffer[bp-1],bp-1);
		pthread_mutex_unlock(&mutex);
		sem_post(&product);
	}
	printf("producer %d is over!\n",id);
}

int consumer(void *args)
{
	int id=*((int*)args);
	int i;
	for(i=0;i<10;i++)
	{
		sleep(10-i);
		sem_wait(&product);
		pthread_mutex_lock(&mutex);
		bp--;
		printf("consumer %d get %s in %d\n",id,buffer[bp],bp);
		strcpy(buffer[bp],"zzz\0");
		pthread_mutex_unlock(&mutex);
		sem_post(&warehouse);
	}
	printf("consumer %d is over!\n",id);
}


 

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值