- 题目:
Fibonacci序列是一组数:0,1,1,2,3,5,8,...,
它可以表达为:
fib(0) = 0
fib(1) = 1
fib(n) = fib(n-1) + fib(n-2)
使用fork()编写一个程序,接受用户在命令行中输入一个数字n,输出Fibonacci序列中的前n个数。
要求:使用shmget在父进程与子进程之间建立一个共享内存段,允许子进程将Fibonacci序列的内容写入共享内存段,父进程等待子进程,当子进程完成后,父进程输出Fibonacci序列。
参考步骤如下: a.接受命令行上传递的参数,执行错误检查 b.创建一个共享内存段 c.将共享内存连接到地址空间 d.创建子进程,调用wait()等待子进程结束 e.子进程计算fibonacci序列,写入共享内存,最后断开此区域 f.父进程在终端上输出共享内存段中的fibonacci序列的值 g.断开并删除内存共享段
- 思路
使用共享内存段,子进程写入共享内存段,父进程输出序列。
- 编译程序
编译链接
cc fibonacci.c
运行
./a.out
输入一个数字n,输出Fibonacci序列中的前n个数
10
0 1 1 2 3 5 8 13 21 34
- 程序说明
/*共享内存的初始化与使用*/
void *shm = NULL;
int shmid; //共享内存标识符
shmid = shmget((key_t)1234, sizeof(share), 0666|IPC_CREAT); //创建共享内存
if(shmid == -1) //错误检查
{
fprintf(stderr, "shmat failed\n");
exit(1);
}
shm = shmat(shmid, 0, 0); //共享内存连接到当前进程的地址空间
if(shm == (void*)-1) //错误检查
{
fprintf(stderr, "shmat failed\n");
exit(1);
}
shared = (int*)shm;
- 题目
用pthread
编写一个多线程程序来输出素数。程序应该这样工作:用户输入运行程序时在命令行输入一个数字,然后输出小于或等于用户输入数的所有素数。请大家思考一下如何利用多线程提高计算速度,希望越快越好(注:不可以在程序中预存结果,最后会公布各位同学程序运行速度的排名)。
- 思路
编写多线程来输出素数,素数采用线性筛法进行识别。
- 编译程序
编译链接
cc pthread.c -lpthread -lm
运行
./a.out
输入一个数字,然后输出小于或等于用户输入数的所有素数
100
2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97
count: 25 //素数数目
time: 0.001055s //运行时间
- 程序说明
/*素数的筛选函数*/
int *shared; //shared中保存着素数,0表示合数,1表示素数
void f(int *n)
{
int j=0, count=0;
shared[0] = 0; //合数
shared[1] = 0; //合数
for(int i=2; i<=(int)sqrt(*n); i++)
{
if(shared[i]) //把素数的倍数全部筛出去
{
for(int j=2*i; j<=*n; j+=i)
shared[j] = 0;
}
}
}
- 题目
解决我们在课堂上学到的读者和写者问题中有利于读者, 可能会让写者饿死的情况。为读者和写者的问题提供另一种有利于写者的解决方案, 即一旦写者等待写入共享数据, 就不会有新的读者开始阅读。使用线程同步编写解决方案。可以自由地使用锁、信号量等来实现。
- 思路
如果有一个写者在等待,则新到来的读者不允许进行读操作。为此应当添加一个整型变量writer_count,用于记录正在等待的写者的数目,当writer_count = 0时,才可以释放等待的读者线程队列。
设置信号量mutex3避免写者同时与多个读者进行竞争,读者中信号量lock比mutex3先释放,则一旦有写者,写者可马上获得资源。即一旦写者等待写入共享数据, 就不会有新的读者开始阅读。
- 编译程序
编译链接
cc writer_reader.c -lpthread
运行
./a.out
输入id,读r或写w,以及操作时间
读者数目: 2
写者数目: 2
读者1:0 4
读者2:3 5
写者1:2 6
写者2:4 7
reader 1 is reading
reader 1 is leaving
writer 1 is writing
writer 1 is leaving
writer 2 is writing
writer 2 is leaving
reader 2 is reading
reader 2 is leaving
- 程序说明
设置两个全局变量writer_count,reader_count记录读者和写者的数量
设置信号量lock,write_lock,read_lock,wrt,mutex3
信号量write_lock在写者的进入区和退出区中使用,对变量writer_count的修改进行互斥
信号量read_lock在读者的进入区和退出区中使用,对变量reader_count的修改进行互斥
信号量lock则是读者和写者两个之间的互斥信号量,保证每次只读或者只写。由于写者优先,写者的操作优于读者,则信号量一直被占用着,直到没有写者才释放。
信号量wrt保证每次只有一个写者进行写操作
信号量mutex3避免写者同时与多个读者进行竞争,读者中信号量lock比mutex3先释放,则一旦有写者,写者可马上获得资源。即一旦写者等待写入共享数据, 就不会有新的读者开始阅读。
/*写者函数*/
void writer(void *d)
{
int id = ((struct data*)d)->id;
int op_time = ((struct data*)d)->op_time;
sleep(op_time); //挂起op_time时间
sem_wait(&write_lock); //信号量write_lock对变量writer_count的修改进行互斥
++writer_count;
if(writer_count == 1) //第一个写者申请信号量lock,其余的写者无需再次申请
sem_wait(&lock); //lock保证每次只读或者只写
sem_post(&write_lock);
sem_wait(&wrt); //信号量wrt来保证每次只有一个写者进行写操作
printf("Thread %d: start writing\n", id);
sleep(1);
printf("Thread %d: end writing\n", id);
sem_post(&wrt);
sem_wait(&write_lock);
--writer_count;
if(writer_count == 0) //最后一个写者释放信号量lock
sem_post(&lock);
sem_post(&write_lock);
}
/*读者函数*/
void reader(void *d)
{
int id = ((struct data*)d)->id;
int op_time = ((struct data*)d)->op_time;
sleep(op_time);
sem_wait(&mutex3); //mutex3避免写者同时与多个读者进行竞争
sem_wait(&lock);
sem_wait(&read_lock); //信号量read_lock对变量reader_count的修改进行互斥
++reader_count;
if(reader_count == 1)
sem_wait(&wrt);
sem_post(&read_lock);
sem_post(&lock);
sem_post(&mutex3);
printf("Thread %d: start reading\n", id);
sleep(1);
printf("Thread %d: end reading\n", id);
sem_wait(&read_lock);
--reader_count;
if(reader_count == 0)
sem_post(&wrt);
sem_post(&read_lock);
}