垃圾回收站

July 19, 2007

Linux并发程序设计

[ 分类: Linux ] 由 弗里曼·潘 发表于 4:48 am 评论( 0 )

背景知识

管道是Linux中最常用的进程间通信IPC机制。利用管道时,一个进程的输出可成为另外一个进程的输入。当输入输出的数据量特别大时,这种IPC机制非常有用。可以想象,如果没有管道机制,而必须利用文件传递大量数据时,会造成许多空间和时间上的浪费。

Linux中,通过将两个file结构指向同一个临时的索引节点,而两个索引节点又指向同一个物理页而实现管道。

实验目的

1) 通过在Linux进程之间进行的通信实例来学习并发程序设计的方法。

2) 通过Linux进程通信的程序设计与实现,进一步熟悉操作系统的进程概念,理解Linux进程管理概念。

3) 通过阅读和分析Linux实验程序,学习Linux程序设计、调试和运行的方法。

工具/准备工作

在开始本实验之前,请回顾教科书的相关内容。

需要准备一台运行Linux操作系统的计算机。

实验内容与步骤

并发程序的设计关键是使用创建进程的系统调用,使一个程序运行时可以生成几个同时运行的程序,如果程序中没有创建进程的动作则为顺序程序设计。

本实验中的并发程序例子完成两个程序childfather之间的数据传递工作,具体做法分为四步。

步骤1编制并发程序pipeline.c

单击红帽子,在”GNOME帮助”菜单中单击”附件”-“文本编辑器”命令,在文本编辑中键入程序并保存为pipeline.c

在该程序中定义管道和文件描述符,并且创建子进程child。该程序用到的系统调用有pipe() dup() fork() closeexecl() exit,它们的功能分别是建立管道、复制文件描述符、创建进程并使子进程与父进程有相同的程序正文、关闭文件描述符、用指定文件覆盖调用程序、撤销当前进程。

清单4-5 pipeline.c

// 定义管道程序

# define STD_INPUT 0 // 定义标准输入设备描述符

# define STD_OUTPUT 1 // 定义标准输出设备描述符

int fd[2];

main()

{

static char process1[]=”father”,process2[]=”child”;

pipe(fd); // 定义管道

pipeline(process1,process2); // 调用自定义函数pipeline()

exit(1); // 程序结束

}

pipeline(char* process1,char* process2)

{

int i;

while ((i=fork())==-1); // 创建进程,直到创建成功为止

if (i)

{

close(fd[0]); // 关闭管道输入描述符

close(STD_OUTPUT); // 关闭标准输出描述符1

dup(fd[1]); // 指定标准输出描述符1为管道写指针

close(fd[1]); // 关闭原始管道写指针

execl(process1, process1, 0); // 用程序father覆盖当前程序

printf(” father failed.\n”); // execl()执行失败

}

else

{

close(fd[1]); // 关闭管道输出描述符

close(STD_INPUT); // 关闭标准输入描述符0

dup(fd[0]); // 指定标准输入描述符0为管道读指针

close(fd[0]); // 关闭原始管道读指针

execl(process2,process2,0); // 用程序child覆盖当前程序

printf(”child failed.\n”); // execl()执行失败

}

exit(2); // 程序结束

}

步骤2编制”管道写”程序father.c作为父进程的一部分工作。其内容如下:

单击红帽子,在”GNOME帮助”菜单中单击”附件”-“文本编辑器”命令,在文本编辑中键入程序并保存为father.c

清单4-6 father.c

main()

{

static char string[] = “Parent is using pipe write.” ;

int len;

len = sizeof(string) ;

write(l, string, len) ; /* string中的内容写入管道中*/

printf(”parent, parent, parent \n \n \n” ) ;

exit(0) ;

}

步骤3编制”管道读”程序child.c作为子进程的一部分工作。其内容如下:

单击红帽子,在”GNOME帮助”菜单中单击”附件”-“文本编辑器”命令,在文本编辑中键入程序并保存为child.c

清单4-7 child.c

main()

{

char output[30] ;

read (0, output, 30) ; /* 从管道中读数据并存入output*/

printf(”%s \n child, child. \n” , output) ;

return(0) ;

}

步骤4编译。

cc -o child child.c

cc -o father father.c

cc -o pipeline pipeline.c

步骤5运行。

./pipeline

若运行不成功,则应该用文本编辑器对源程序进行修改调试。

运行显示结果为:

____________________________________________________________________

________________________________________________________________________

________________________________________________________________________

提示本实验程序例子中forkexeclpipeclosedupreadwrite等是系统调用,它们的使用方法细节可参见程序员参考手册。


Crontab 笔记

[ 分类: Linux ] 由 弗里曼·潘 发表于 2:24 am 评论( 0 )

作者:Fenng |

English Version 【可以转载, 转载时务必以超链接形式标明文章原始出处和作者信息及版权声明
网址:

关于 Crontab ,维基百科上的词条 Crontab非常好。可惜这个地址在国内不用代理访问不到。

虽然关于 Crontab 的介绍到处都是,详细读了一遍这个词条,收获还是有的。Crontab 这个名字来自 “chronos”,一个古希腊语, “时间”的意思.

常见陷阱

每个SA、DBA 或者是普通的 Unix 用户,在第一次使用 Crontab 的时候都会遇到问题. 运行 Crontab 的常见错误包括如下几种:

1) 出于测试目的新创建了一条 Cron JOB, 时间间隔必须超过两分钟,否则 JOB 将调度不到。如果必须忽略这两分钟的载入配置时间差,可以通过重新启动 Cron Daemon 做到。

2) 从 Crontab 中启动 X Window 程序需要注意的事项:所以要么在程序前初始化 “DISPLAY=:0.0″, 要么在应用程序后面追加参数 –display :0.0

3) 命令中的 % 必须做转义处理: \% .我个人的意见是不要在命令行里带这个参数,干脆写到脚本里,然后调度该脚本即可。

其实我倒是认为使用 Crontab 最常见的一个问题往往是因为环境变量不对。经常会看到论坛里有人问:为什么我的 Crontab 创建了不执行? 准备创建一条 Cron JOB 的时候,很多人都喜欢在命令行下运行一遍,因为这个时候环境变量是随着 Shell 自动带进来,在 Crontab 中则可能因为找不到正确的环境变量,JOB 就不能执行。这个小问题就像出天花,一次教训之后就都记得了。

必须使用的一则技巧

每条 JOB 执行完毕之后,系统会自动将输出发送邮件给当前系统用户。日积月累,非常的多,甚至会撑爆整个系统。所以每条 JOB 命令后面进行重定向处理是非常必要的: >/dev/null 2>&1 。前提是对 Job 中的命令需要正常输出已经作了一定的处理, 比如追加到某个特定日志文件。

附: Crontab 的格式说明如下:

* 逗号(’,') 指定列表值。如: “1,3,4,7,8″
* 中横线(’-') 指定范围值 如 “1-6″, 代表 “1,2,3,4,5,6″
* 星号 (’*') 代表所有可能的值

Linux(开源系统似乎都可以)下还有个 “/” 可以用. 在 Minute 字段上,*/15 表示每 15 分钟执行一次. 而这个特性在商业 Unix ,比如 AIX 上就没有.

# Use the hash sign to prefix a comment
# +---------------- minute (0 - 59)
# |  +------------- hour (0 - 23)
# |  |  +---------- day of month (1 - 31)
# |  |  |  +------- month (1 - 12)
# |  |  |  |  +---- day of week (0 - 7) (Sunday=0 or 7)
# |  |  |  |  |
# *  *  *  *  *  command to be executed



« Previous PageNext Page »