操作系统实验-进程

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); 
}



  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
1. 实验目的 1) 加深对进程概念的理解,明确进程和程序的区别。 2) 进一步认识并发执行的实质。 3) 分析进程争用资源的现象,学习解决进程互斥的方法。 4) 学习解决进程同步的方法。 5) 了解Linux系统进程通信的基本原理。   进程是操作系统中最重要的概念,贯穿始终,也是学习现代操作系统的关键。通过本次实验,要求理解进程的实质和进程管理的机制。在Linux系统下实现进程从创建到终止的全过程,从中体会进程的创建过程、父进程和子进程之间的关系、进程状态的变化、进程之间的互斥、同步机制、进程调度的原理和以管道为代表的进程间的通信方式的实现。 2. 内容及要求:   这是一个设计型实验,要求自行编制程序。   使用系统调用pipe()建立一条管道,两个子进程分别向管道写一句话:   Child process1 is sending a message!   Child process2 is sending a message!   父进程从管道读出来自两个子进程的信息,显示在屏幕上。   要求: 1) 父进程先接收子进程1发来的消息,然后再接收子进程2发来的消息。 2) 实现管道的互斥使用,当一个子进程正在对管道进行写操作时,另一子进程必须等待。使用系统调用lockf(fd[1],1,0)实现对管道的加锁操作,用lockf(fd[1],0,0)解除对管道的锁定。 3) 实现父子进程的同步,当子进程把数据写入管道后,便去睡眠等待;当父进程试图从一空管道中读取数据时,也应等待,直到子进程将数据写入管道后,才将其唤醒。 3.相关系统调用 1) fork() 用于创一个子进程。 格式:int fork(); 返回值:在子进程中返回0;在父进程中返回所创建的子进程的ID值;当返回-1时,创建失败。 2) wait() 常用来控制父进程与子进程的同步。 在父进程调用wait(),则父进程被阻塞,进入等待队列,等待子进程结束。当子进程结束时,父进程从wait()返回继续执行原来的程序。 返回值:大于0时,为子进程的ID值;等于-1时,调用失败。 3) exit() 是进程结束时最常调用的。 格式:void exit( int status); 其中,status为进程结束状态。 4) pipe() 用于创建一个管道 格式:pipe(int fd); 其中fd是一个由两个数组元素fd[0]和fd[1]组成的整型数组,fd[0]是管道的读端口,用于从管道读出数据,fd[1] 是管道的写端口,用于向管道写入数据。 返回值:0 调用成功;-1 调用失败。 5) sleep() 调用进程睡眠若干时间,之后唤醒。 格式:sleep(int t); 其中t为睡眠时间。 6) lockf() 用于对互斥资源加锁和解锁。在本实验中,该调用的格式为: lockf(fd[1],1,0);/* 表示对管道的写入端口加锁。 lockf(fd[1],0,0);/* 表示对管道的写入端口解锁。 7) write(fd[1],String,Length) 将字符串String的内容写入管道的写入口。 8) read(fd[0],String,Length) 从管道的读入口读出信息放入字符串String中。 4.程序流程 父进程: 1) 创建管道; 2) 创建子进程1; 3) 创建子进程2; 4) 等待从管道中读出子进程1写入的数据,并显示在屏幕上; 5) 等待从管道中读出子进程2写入的数据,并显示在屏幕上; 6) 退出。 子进程: 1) 将管道的写入口加锁; 2) 将信息“Child process n is sending message!”输入到变量OutPipe中,n=1,2; 3) 将OutPipe中信息写入管道; 4) 睡眠等待; 5) 将管道的写入口解锁; 6) 退出。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值