关于Operating System建立thread的程序,多个thread共享一个circular buffer,按照一定的顺序对这个buffer进行操作。因为每个thread写入之后要sleep一段时间,然后把CPU分配到其他thread上。我这个程序可以正确运行,但是如果thread非常多,共同操作一个buffer,系统运行速度就会很慢。可能是因为CPU在多个thread之上不停的转换造成的。
下面是这个程序的要求说明。
Write an ansi C program called q1.c that is
invoked as follows:
% q1 <max> <bufferSize> <nWriters> <nReaders> <resultsFile>
The progam should create <nWriters + nReaders> threads/pthreads
(not child processes).
They share a circular buffer of size <bufferSize>.
Each buffer slot is capable of holding 2 ints, namely the number of
the thread (1 .. nWriters) and a second int in the range (1 .. <max>).
Each writer thread repeatedly writes a pair of ints into the next free
buffer slot. These pairs are
(threadNumber, 1), (threadNumber, 2), ... , (threadNumber, <max>).
After writing one such pair, the thread sleeps a random length of time
between 0 and .1 seconds. Use nanosleep for this (% man nanosleep).
Each reader thread repeatedly reads the next available (threadNumber, n)
pair from the buffer and then appends them to the <resultFile> as
threadNumber n\n
i.e. the threadNumber followed by a single blank followed by the int
followed by a newline character. (Note that some testing will be done
with a script, so adhering to this output format is important.)
In all, your program should output <nWriters>*<max> lines.
After reading one such pair, the the thread sleeps a random length of time
between 0 and .1 seconds. Use nanosleep for this (% man nanosleep).
The threads should use all buffer slots,
i.e. with indexes from 0 up to <bufferSize>-1.
Example: the call
% q1 5 3 2 4 temp
(i.e. max of 5, buffer size of 3, 2 writer threads, 4 reader threads
and output going to a file called temp)
could result in the following 10 lines being written to temp:
1 1
1 2
2 1
1 3
2 2
1 4
2 3
2 4
2 5
1 5
Your solution should not make assumptions about thread scheduling or
count on (or try to enforce) any particular alternation or sequencing
among the threads.
Compiling
=========
We will compile your programs using
% cc -Wall -o q1 q1.c -lpthread
#define BUFLEN 100 /* define the length of buffer used by sprintf */
#define TRUE 1 /* truth status used by critical section */
#define FALSE 0 /* false status used by critical section */

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <string.h>
#include <time.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <pthread.h>
#include <unistd.h>
/* global variable accessed by threads */
/* variables used to store the input integers */
int max;
int bufferSize;
int nWriters;
int nReaders;
int mutex = 1; /* used by binary semaphore */
int read_number = 0; /* count the number of pairs to be read */
int in = 0; /* write position of the circular array */
int out = 0; /* read position of the circular array */
int fd; /* file descriptor */
int full = FALSE; /* indicate status of the buffer when buffer size is 1 */
char buf[BUFLEN]; /* buffer used by sprintf */
struct timespec ts; /* declaring a timespec struct */
/* define struct type */
typedef struct {
int threadNumber;
int number;
}item;
item (*Pbuffer)[]; /* declaring a pointer to the buffer */
/* function declaration */
void * Writers(int);
void * Readers(void *);
int TestAndSet(int *);
/* wait operation of the binary semaphore */
void wait(int *mux)
{
while(*mux == 0)
;
*mux = 0;
}
/* signal operation of the binary semaphore */
void signal(int *mux)
{
*mux = 1;
}
int main(int argc, char ** argv)
{
int thread_number; /* record thread number */
int error; /* indicates the error number */
int i; /* used as a counter of the loop */
char* resultsFile; /* store file name */
pthread_t tid; /* store thread ID */
if (argc < 6)
{
fprintf(stderr, "missing argument, usage: q1 <max> <bufferSize> <nWriters> <nReaders> <resultsFile>\n");
exit(-1);
}
/* save arguments */
max = atoi(argv[1]);
bufferSize = atoi(argv[2]);
nWriters = atoi(argv[3]);
nReaders = atoi(argv[4]);
resultsFile = argv[5];
item buffer[bufferSize]; /* make a new buffer used to store elements */
Pbuffer = &buffer; /* let globle pointer point to the buffer, then threads can access the buffer */
srand(time(NULL)); /*The pseudo-random number generator is initialized using the seed. */ 
/* establish the connection between a file and a file descriptor */
if ((fd = open(resultsFile, O_CREAT | O_TRUNC | O_WRONLY, S_IRUSR | S_IWUSR)) == -1)
{
perror(resultsFile);
exit(-1);
}
/* create threads which will write the buffer, and pass thread numbers as argument to threads */
for (thread_number = 1; thread_number <= nWriters; thread_number++)
{
if ((error = pthread_create(&tid, NULL, (void *)Writers, (void *)thread_number)))
{
fprintf(stderr, "Cannot create thread:%s\n", strerror(error));
exit(1);
}
}
/* create threads which will read the buffer */
for (i = 0; i < nReaders; i++)
{
if ((error = pthread_create(&tid, NULL, Readers, NULL)))
{
fprintf(stderr, "Cannot create thread:%s\n", strerror(error));
exit(1);
}
}
/* Wait until the last thread terminates. Any thread can terminates only when all things on the buffer have been written on file */
pthread_join(tid, NULL);
/* close the file descriptor */
close(fd);
return 0;
}
/* Write buffer */
void * Writers(int thread_number)
{
struct timespec ts; /* The structure encapsulates seconds and ns */
int counter = 1; /* counte the number from 1 to max */ 
while (counter <= max)
{
wait(&mutex);
/* buffer is not full */
if ((in + 1) % bufferSize != out)
{
/************ critical section *************/
/* write pairs on buffer */
(*Pbuffer)[in].threadNumber = thread_number;
(*Pbuffer)[in].number = counter;
in = (in + 1) % bufferSize; /* increase the writing position on buffer */
counter++; /* increase the counter */
signal(&mutex);
/************ remainder section *************/
ts.tv_nsec = rand() % 100000000;
nanosleep(&ts, NULL); /* the thread sleeps a random length of time between 0 and .1 seconds */
}
/* when buffer size is 1, and buffer is not full */
else if (bufferSize == 1 && full == FALSE)
{
/************ critical section *************/
/* write pairs on buffer */
(*Pbuffer)[in].threadNumber = thread_number;
(*Pbuffer)[in].number = counter;
full = TRUE; /* set the buffer to be full */
counter++; /* increase the counter */
signal(&mutex); 
/************ remainder section *************/
ts.tv_nsec = rand() % 100000000;
nanosleep(&ts, NULL); /* the thread sleeps a random length of time between 0 and .1 seconds */
}
/* buffer is full */
else
{
signal(&mutex);
/************ remainder section *************/
ts.tv_nsec = rand() % 100000000;
nanosleep(&ts, NULL); /* the thread sleeps a random length of time between 0 and .1 seconds */
}
}
return NULL;
}
/* Read buffer */
void * Readers(void * arg)
{
struct timespec ts; /* The structure encapsulates seconds and ns */
/* there are totally nWriters * max pairs to be read */
while(read_number < nWriters * max)
{
wait(&mutex);
/************ critical section *************/
/* if all pairs have been read, then terminate */
if (read_number >= nWriters * max)
break;
/* buffer is not empty */
if (in != out)
{
/* read buffer and write to file */
sprintf(buf, "%d %d\n", (*Pbuffer)[out].threadNumber, (*Pbuffer)[out].number);
write(fd, buf, strlen(buf));
out = (out + 1) % bufferSize; /* increase the reading position on buffer */
read_number++; /* increase the number of pairs which have been read */
signal(&mutex);
/************ remainder section *************/
ts.tv_nsec = rand() % 100000000;
nanosleep(&ts, NULL); /* the thread sleeps a random length of time between 0 and .1 seconds */
}
/* when buffer size is 1, and buffer is full */
else if (bufferSize == 1 && full == TRUE)
{
/* read buffer and write to file */
sprintf(buf, "%d %d\n", (*Pbuffer)[out].threadNumber, (*Pbuffer)[out].number);
write(fd, buf, strlen(buf));
full = FALSE; /* set the buffer to be full */
read_number++; /* increase the number of pairs which have been read */
signal(&mutex);
/************ remainder section *************/
ts.tv_nsec = rand() % 100000000;
nanosleep(&ts, NULL); /* the thread sleeps a random length of time between 0 and .1 seconds */
}
/* when buffer is empty */
else
{
signal(&mutex);
/************ remainder section *************/
ts.tv_nsec = rand() % 100000000;
nanosleep(&ts, NULL); /* the thread sleeps a random length of time between 0 and .1 seconds */
}
}
return NULL;
}


浙公网安备 33010602011771号