Linux线程控制课后作业

1、分析6.3节开头的程序sharvar .c

#include"wrapper.h"
#define N 2
void* thread(void* vargp);
char** ptr;
int main()
{
	int i;
	pthread_ t tid;
	char* mesgs[N] = {
		"Hello to thread O",
		"Hello to thread "
	};

	ptr = mesgs;
	for (i = 0; i < N; i++)
		pthread_create(&tid, NULL, thread, (void*)i);
	pthread_exit();
}
void *thread(void* vargp)
{
	int mytid = (int)vargp;
	static int cnt = 0;
	cnt++;
	printf("[ % d] : % ( cnt-% d) n", mytid, ptr[myid], cnt);
	return;
}
(1)如果约定自动变量的运行实例用符号vt表示,v为变量名,t为线程名,可取m(主线程)t(对等线程0)或t1(对等线程1),表示该运行实例驻留在线程t的本地栈中,请问程序的每个变量有哪些运行实例,如何表示。
(2)每个运行实例被哪些线程引用?
(3)程序中有哪些共享变量?
答:

(1)i.m、pid.m、mesgs.m、mytid.to、mytid.t1、cnt.to

(2)mesgs.m被t0和t1引用、i.m被t0和t1引用

(3)thread、ptr、cnt

2、编写一个程序,创建两个对等线程T1、T2,分别计算数列1、2、N的和以及平方和的平方根,主线程准备数据和输出结果。主线程利用全局变量与T1交换数据,通过pthread_create 、pthread exit 调用参数与线程T2交换数据。

#include
#include
#include

using namespace std;

//与线程t0交互的全局变量
int result_t0 = 0;
int n_t0 = 10;

//求和
void* sum(void* arg);
//求平方和开方
void* SqurSum(void* arg);

int main()
{
	//创建线程
	pthread_t t0, t1;
	pthread_create(&t0, nullptr, sum, nullptr);
	pthread_create(&t1, nullptr, SqurSum, reinterpret_cast<void*>(10));
	
	//等待线程结束
	void* res;
	pthread_join(t0, nullptr);
	pthread_join(t1, &res);

	//输出结果
	cout << "t0 result: " << result_t0 << endl;
	cout << "t1 result: " << reinterpret_cast<long int>(res) << endl;
}

void* sum(void* arg)
{
	int num = n_t0;
	for (int i = 1; i <= num; ++i)
		result_t0 += i;
}

void* SqurSum(void* n)
{
	int result;
	int num = reinterpret_cast<long int>(n);
	for (int i = 1; i <= num; ++i)
		result += pow(i,2);
	result = sqrt(result);
	pthread_exit(reinterpret_cast<void*>(result));
}

在这里插入图片描述

3、考虑赋值语句的汇编代码实现,分析下面的程序有哪几种可能的输出结果

int k = 0;
void* thread(void* arg)
{
	k = k + 10;
}
int main()
{
	pthread_ttl, t2, t3;
	pthread_ create(&t1, NULL, thread, NULL); 
	pthread_ create(&t2, NULL, thread, NULL); 
	pthread_ create(&t3, NULL, thread, NULL); 
	pthread_join(t1, NULL); 
	pthread_join(t2, NULL); 
	pthread_join(t3, NULL); 
	printf("k=%d\n", k);
}

k=10、k=20、k=30

4、考虑赋值语句的汇编代码实现,分析下面的程序有哪几种可能的输出结果

int x = 0,y = 0;

void* thread1(void* arg){ x = y + 5; }

void* thread2(void* arg) { y = x + 10; }

int main()
{
	pthread_ttl, t2, t3;
	pthread_create(&t1, NULL, thread1, NULL);
	pthread_create(&t2, NULL, thread2, NULL);

	pthread_join(t1, NULL);
	pthread_join(t2, NULL);
	printf("x=%d y=%d", x, y);
}

x=5 y=15

x=5 y=10

x=15 y=10

5、阅读下列程序,画出程序的并发关系图,给出程序中4个位置的指定变量有哪几种可能的结果。

int flag = 1;

void func() { flag = flag + 5; }

void main()
{
	int status, ret;
	pid_t pid;
	void func();
	flag = flag + 15; //问题一:flag = ?
	printf("1 st question: flag=%dn", flag);

	signal(SIGUSR1, func);
	if (pid = fork()) {
		flag = flag + 5;//问题二:flag = ?
		printf(" 2nd question: flag-%dn", flag);
		kill(pid, SIGUSR1);
		wait(&status);
		ret = WEXITSTATUS(status);//问题三:ret = ?
		printf("5th question: status= % dn", ret);
	}
	else {
		flag = flag + 50;//问题四:flag = ?
		printf("3rd question: flag=%", flag);
		exit(80);
	}
}

Linux线程控制课后作业_第1张图片

问题1:flag=16

问题2:flag=21

问题3:ret=80,子进程exit时返回了80

问题4:ret=66,子进程在父进程没有发送信号前运行结束;ret=71子进程在父进程发送信号并接受到信号后结束;ret=15,子进程在进行flag = flag+50时,接收到父进程的信号,此时对于func函数的执行,寄存器中仍然保持着没有修改的flag值,故执行完后,会写入21到flag存储的位置。

6、编写程序测量pthread create 、fork两个函数的运行时间,并进行比较

#include
#include
#include
#include
#include
#include

using namespace std;

//测试函数
void* test(void* arg);

int main()
{
    pthread_t t0;
    struct timeval time_start;//开始测试时间
    struct timeval time_end;//结束测试时间
    //测试pthread_create
    gettimeofday(&time_start, nullptr);
    pthread_create(&t0, nullptr, test, nullptr);
    gettimeofday(&time_end, nullptr);
    double wa = time_end.tv_usec - time_start.tv_usec;
    double sa = time_end.tv_sec - time_start.tv_sec;
    double ms = wa / 1000.0 + sa * 1000.0;
    pthread_join(t0, nullptr);
    cout <<"pthread_create: "<< ms << "ms" << endl;
    //测试fork
    gettimeofday(&time_start, nullptr);
    if (fork() == 0)
    {
        test(nullptr);
        exit(0);
    }
    gettimeofday(&time_end, nullptr);
    wa = time_end.tv_usec - time_start.tv_usec;
    sa = time_end.tv_sec - time_start.tv_sec;
    ms = wa / 1000.0 + sa * 1000.0;
    cout << "fork: " << ms << "ms" << endl;
}

void* test(void* arg)
{
    cout << "test" << endl;
}

Linux线程控制课后作业_第2张图片

7、分析下面程序中每个变量各有哪几个运行实例,哪些变量是共享变量,它们由哪些线程引用,哪些共享变量被并发读写

# define N 4
void* thread(void* vargp);
int a[10 * N];
int cnt[N], sum = 0;
int main()
{
	pthread_t tid[N];
	int i, k;
	for (k = 0; k < 10 * N; i++) a[k] = k;
	for (i = 0; i < N; i++)
		pthread_create(&tid[i], NULL, thread, &i);
	for (i = 0; i < N; i++)
		pthread_join(tid[i], NULL);
	for (i = 0; i < N; i++);
	sum = sum + cnt[i];
	printf("the sum % dn", sum);
	exit(0);
}
void* thread(void* vargp)
{
	int myid = *((int*)vargp);
	int k; 
	cnt[myid] = 0; 
	for (k = 10 * myid; k < 10 * myid + 10; k++)
		cnt[myid] = cnt[myid] + a[k];
	return NULL;
}

全局变量实例:a(共享变量,被main写,被tn线程并发读)、cnt(共享变量,被main读,被tn线程并发写)、sum(被main读写)

main变量实例:tid、i(共享变量,被main写,被tn线程引用)、k

tn线程变量实例:myid、k

你可能感兴趣的:(Linux,课后作业,操作系统,thread,多线程,并发编程,linux,操作系统)