1、 实验目的
熟悉Linux下进程管理和相关的系统调用。
2、 实验内容
(1). Linux 下用线程模拟实现“生产-消费者”或“读者-写者”或“哲学家就餐”同步问题。
将设计分析过程和源代码写入实验报告。
(2). 补缺三段代码,并回答问题。
将设计分析过程和源代码写入实验报告。
3、实验代码
(1) 进程
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <signal.h>
#include <ctype.h>
/* 允许建立的子进程个数最大值 */
#define MAX_CHILD_NUMBER 10
/* 子进程睡眠时间 */
#define SLEEP_INTERVAL 2
int proc_number=0; /* 子进程的自编号,从0开始 */
void do_something();
int main(int argc, char* argv[])
{
int child_proc_number = MAX_CHILD_NUMBER; /* 子进程个数 */
int i, ch;
pid_t child_pid;
pid_t pid[10]={0}; /* 存放每个子进程的id */
if (argc > 1)
{
/* 命令行参数中的第一个参数表示建立几个子进程,最多10个 */
child_proc_number = atoi(argv[1]);
child_proc_number
= (child_proc_number > 10) ? 10 : child_proc_number;
}
for (i=0; i<child_proc_number; i++)
{
child_pid = fork();
if(child_pid > 0)
{
pid[i] = child_pid;
}
else if(child_pid == 0)
{
proc_number = i;
do_something();
}
else
{
perror("fail to fork!\n");
}
/* 在这里填写代码,建立child_proc_number个子进程
* 子进程要执行
* proc_number = i;
* do_something();
* 父进程把子进程的id保存到pid[i] */
}
/* 让用户选择杀死哪个进程。输入数字(自编号)表示杀死该进程
* 输入q退出 */
while ((ch = getchar()) != 'q')
{
if (isdigit(ch))
{
kill(pid[ch-'0'], SIGTERM);
/* 在这里填写代码,向pid[ch-'0']发信号SIGTERM,
* 杀死该子进程 */
}
}
/* 在这里填写代码,杀死本组的所有进程 */
kill(0, SIGTERM);
return 0;
}
void do_something()
{
for(;;)
{
printf("This is process No.%d and its pid is %d\n", proc_number, getpid());
sleep(2); /* 主动阻塞两秒钟 */
}
}
(2)线程
/* POSIX 下线程控制的实验程序残缺版 */
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <ctype.h>
#include <pthread.h>
#include<stdlib.h>
#include<semaphore.h>
#define MAX_THREAD 3 /* 线程的个数 */
unsigned long long main_counter, counter[MAX_THREAD]; /* unsigned long long是比long还长的整数 */
//sem_t S1;
void* thread_worker(void*);
int main(int argc, char* argv[])
{
int i, rtn, ch;
pthread_t pthread_id[MAX_THREAD] = {0}; /* 存放线程id*/
//sem_init(&S1,0,1);
for (i=0; i<MAX_THREAD; i++) {
/* 在这里填写代码,用pthread_create建一个普通的线程,
线程id存入pthread_id[i],线程执行函数是thread_worker
并i作为参数传递给线程 */
// if(pthread_create(&pthread_id[i], NULL, thread_worker, &i)!=0){
if(pthread_create(&pthread_id[i], NULL, thread_worker, (void *)i)!=0){
printf("thread_create failed");
exit(1);
}
}
do {/* 用户按一次回车执行下面的循环体一次。按q退出 */
unsigned long long sum = 0;/* 求所有线程的counter的和 */
for (i=0; i<MAX_THREAD; i++) {/* 求所有counter的和 */
sum += counter[i];
printf("counter[%d]=%llu ", i,counter[i]);
}
printf("%llu/%llu", main_counter, sum);
} while ((ch = getchar()) != 'q');
//sem_destroy(&S1);
return 0;
}
void* thread_worker(void* p) {
int thread_num;
/* 在这里填写代码,把main中的i的值传递给thread_num */
//thread_num = *(int*)p;
thread_num = (int)(p);
for(;;) { /* 无限循环 */
counter[thread_num]++; /* 本线程的counter加一 */
//sem_wait(&S1);
main_counter++; /* 主counter 加一 */
//sem_post(&S1);
}
}
(3)互斥
//* POSIX 下线程死锁的演示程序 */
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <ctype.h>
#include <pthread.h>
#define LOOP_TIMES 10000
pthread_mutex_t mutex1 = PTHREAD_MUTEX_INITIALIZER; /*用宏PTHREAD_MUTEX_INITIALIZER来初始化 */
pthread_mutex_t mutex2 = PTHREAD_MUTEX_INITIALIZER;
void* thread_worker(void*);
void critical_section(int thread_num, int i);
int main(void) {
int rtn, i;
pthread_t pthread_id = 0; /* 存放子线程的id */
rtn = pthread_create(&pthread_id, NULL, thread_worker, NULL );
if(rtn != 0) {
printf("pthread_create ERROR!\n");
return -1;
}
for (i=0; i<LOOP_TIMES; i++) {
pthread_mutex_lock(&mutex1);
pthread_mutex_lock(&mutex2);
critical_section(1, i);
pthread_mutex_unlock(&mutex2);
pthread_mutex_unlock(&mutex1);
}
pthread_mutex_destroy(&mutex1);
pthread_mutex_destroy(&mutex2);
return 0;
}
void* thread_worker(void* p) {
int i;
for (i=0; i<LOOP_TIMES; i++) {
// pthread_mutex_lock(&mutex2);
//pthread_mutex_lock(&mutex1);
pthread_mutex_lock(&mutex1);
pthread_mutex_lock(&mutex2);
critical_section(2, i);
pthread_mutex_unlock(&mutex2);
pthread_mutex_unlock(&mutex1);
}
}
void critical_section(int thread_num, int i) {
printf("Thread%d: %d\n", thread_num, i);
}
(4)模拟生产者-消费者
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <semaphore.h>
#define M 10
int in = 0;
int out = 0;
int buff[M] = {0};
sem_t empty_sem;
sem_t full_sem;
pthread_mutex_t mutex;
int producer = 0;
int consumer = 0;
void print()
{
int i;
for(i = 0; i < M; i++)
printf("%d ", buff[i]);
printf("\n");
}
void *product()
{
while(1)
{
sleep(1);
sem_wait(&empty_sem);
pthread_mutex_lock(&mutex);
in = in % M;
printf("producer at %d position: \t", in);
buff[in] = 1;
print();
++in;
pthread_mutex_unlock(&mutex);
sem_post(&full_sem);
}
}
void *prochase()
{
while(1)
{
sleep(2);
sem_wait(&full_sem);
pthread_mutex_lock(&mutex);
out = out % M;
printf("consumer at %d position: \t", out);
buff[out] = 0;
print();
++out;
pthread_mutex_unlock(&mutex);
sem_post(&empty_sem);
}
}
int main()
{
pthread_t id1;
pthread_t id2;
int ret;
int ini1 = sem_init(&empty_sem, 0, M);
int ini2 = sem_init(&full_sem, 0, 0);
if(ini1 && ini2 != 0)
{
printf("sem init failed \n");
exit(1);
}
int ini3 = pthread_mutex_init(&mutex, NULL);
if(ini3 != 0)
{
printf("mutex init failed \n");
exit(1);
}
ret = pthread_create(&id1, NULL, product,NULL);//
if(ret != 0)
{
printf("product creation failed \n");
exit(1);
}
ret = pthread_create(&id2, NULL, prochase, NULL);
if(ret!= 0)
{
printf("prochase creation failed \n");
exit(1);
}
pthread_join(id1,NULL);
pthread_join(id2,NULL);
exit(0);
}