使用fork()编写一个c语言程序。它在子进程中生成Fibonacci数列,数列号码在命令行中提供。例如,如果提供的是5,Fibonacci数列中的前5个数将由子进程产生。在子进程生成数列之后,该数列由父进程输出。使用共享内存实现。该题目原题如下:
1. linux下的错误捕获
linux下错误的捕获:errno和strerror
errno是一个全局变量,包含在头文件#include
#include
#include
#include
int main(void)
{
int fd;
extern int errno;
if((fd =open("/dev/dsp",O_WRONLY)) < 0)
{
printf("errno=%d\n",errno);
}
exit(0);
}
如果dsp设备忙的话errno值将是16.
strerror用于解释errno.用法如下:
#include
#include
#include
int main(void)
{
int fd;
extern int errno;
if((fd =open("/dev/dsp",O_WRONLY)) < 0)
{
printf("errno=%d\n",errno);
char * mesg = strerror(errno);
printf("Mesg:%s\n",mesg);
}
exit(0);
}
dsp设备忙的话将输出如下:
errno=16
Mesg:Device or resource busy
更多:http://blog.csdn.net/starstar1992/article/details/52756387
2. shmget, shmat, shmdt, shmctl
int shmget(key_t key, size_t size, int flag);
/*
创建或打开共享存储区
key: 标识符的规则
size:共享存储段的字节数
flag:读写的权限
返回值:成功返回共享存储的id,失败返回-1
*/
void *shmat(int shmid, const void *addr, int flag);
/*
连接共享存储区
shmid:共享存储的id
addr:一般为0,表示连接到由内核选择的第一个可用地址上,否则,如果flag没有指定SHM_RND,则连接到addr所指定的地址上,如果flag为SHM_RND,则地址取整
flag:如前所述,一般为0
返回值:如果成功,返回共享存储段地址,出错返回-1
*/
int shmdt(void *addr);
/*
拆除共享存储区连接
addr:共享存储段的地址,以前调用shmat时的返回值
当一个进程不再需要共享内存段时,它将调用shmdt()系统调用取消这个段,但是,这并不是从内核真正地删除这个段,而是把相关shmid_ds结构的shm_nattch域的值减1,当这个值为0时,内核才从物理上删除这个共享段
*/
int shmctl(int shmid,int cmd,struct shmid_ds *buf)
/*
共享存储区控制
shmid:共享存储段的id
cmd:一些命令
IPC_STAT 得到共享内存的状态
IPC_SET 改变共享内存的状态
IPC_RMID 删除共享内存
IPC_RMID 命令实际上不从内核删除一个段,而是仅仅把这个段标记为删除,实际的删除发生在最后一个进程离开这个共享段时。
请注意,共享内存不会随着程序结束而自动消除,要么调用shmctl删除,要么自己用手敲命令去删除,否则永远留在系统中。
*/
更多:http://lobert.iteye.com/blog/1746041
3. int main(int argc,char* argv[])详解
argc是命令行总的参数个数 ,记录用户输入的参数个数。
argv[]为保存命令行参数的字符串指针,其中第0个参数是程序的全名,以后的参数为命令行后面跟的用户输入的参数,argv参数是字符串指针数组,其各元素值为命令行中各字符串(参数均按字符串处理)的首地址。 指针数组的长度即为参数个数argc。数组元素初值由系统自动赋予。比如:
int main(int argc, char* argv[])
{
int i;
for(i = 0; icout<cin>>i;
return 0;
}
执行时敲入
F:\MYDOCU~1\TEMPCODE\D1\DEBUG\D1.EXE aaaa bbb ccc ddd
输出如下:
F:\MYDOCU~1\TEMPCODE\D1\DEBUG\D1.EXE
aaaa
bbb
ccc
ddd
更多:http://www.cnblogs.com/clumsy1006/archive/2013/10/11/3362658.html
4. assert的用法
assert宏的原型定义在assert.h中, 其作用是如果它的条件返回错误,则终止程序执行,原型定义:
#include <assert.h>
void assert( int expression );
常用在函数开始处检验传入参数的合法性,如:
int resetBufferSize(int nNewSize)
{
//功能:改变缓冲区大小,
//参数:nNewSize 缓冲区新长度
//返回值:缓冲区当前长度
//说明:保持原信息内容不变 nNewSize<=0表示清除缓冲区
assert(nNewSize >= 0);
assert(nNewSize <= MAX_BUFFER_SIZE);
...
}
更多:http://www.cnblogs.com/ggzss/archive/2011/08/18/2145017.html
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
//#include
#define MAX_SEQUENCE 10
#define PERM S_IRUSR | S_IWUSR//使当前用户可以读写这个区域
typedef struct{
int fib_sequence[MAX_SEQUENCE];
int sequence_size;
}share_data;
void Fibonacci(int n, int *Fibo){//获得斐波那契数列
//assert(n >= 10);
if(n == 0){
Fibo[0] = 0;
return;
}
Fibo[0] = 0;
Fibo[1] = 1;
if(n == 1){
return;
}
for(int i=2; i< n;i++){
Fibo[i] = Fibo[i-1] + Fibo[i-2];
}
}
int main(){
int num;
int shmid;//共享内存ID
char *shmptr;//父类共享内存地址指针
share_data *shMemory;//创建结构体指针
pid_t pid;
printf("Please enter a positive number(no more than 10): ");
while(1){
scanf("%d", &num);
if(num < 0) printf("The number less than 0. Please try agian: ");
else if(num > 10) printf("The number more than 0. Please try agian: ");
else break;
}
//IPC_PRIVATE 保证使用唯一ID
if((shmid = shmget(IPC_PRIVATE, sizeof(share_data), PERM)) < 0)
{//创建共享内存
printf("shmget error:%s\n", strerror(errno));
return -1;
}
if((shMemory = (share_data*)shmat(shmid, 0, 0)) == (void*)-1)
{//将共享内存连接到可用地址上
printf("shmat error:%s\n", strerror(errno));
return -1;
}
shMemory->sequence_size = num;
while((pid = fork()) == -1);//创建子进程
if(pid == 0){//在子进程中生成斐波那契数列
Fibonacci(shMemory->sequence_size, shMemory->fib_sequence);
exit(0);
}
else if(pid > 0){//父进程中,执行 输出
wait(0);
for(int i = 0; i < shMemory -> sequence_size; i++){
printf("%d ", shMemory->fib_sequence[i]);
}
printf("\n");
shmdt(shMemory);//取消此内存
shmctl(shmid, IPC_PRIVATE, NULL);//回收该内存段
exit(0);
}
return 0;
}
1. 注意不要漏了头文件wait.h,否则编译过程中会出现警告。
2. 由于头文件sys/ipc.h的存在 ,编译要使用下面的命令:
否则会出现警告:
原因与解决:http://www.justskins.com/forums/_svid_source-and-_xopen_source-263518.html
本次实验讲解到这里结束,希望对大家有帮助。