操作系统课程设计实验报告
专业:信息安全
班级:0903
姓名:付晓帆
学号:U200915328
一、 实验目的
掌握 Linux 操作系统的使用方法;
了解 Linux 系统内核代码结构;
掌握实例操作系统的实现方法。
二、 实验要求
1、 掌握 Linux 操作系统的使用方法,包括键盘命令、系统调用;掌握在 Linux
下的编程环境。
编一个 C 程序,其内容为实现文件拷贝的功能;
编一个 C 程序,其内容为分窗口同时显示三个并发进程的运行结
果。要求用到 Linux 下的图形库。
2、 掌握系统调用的实现过程,通过编译内核方法,增加一个新的系统调用。
另编写一个应用程序,调用新增加的系统调用。
实现的功能是:文件拷贝;
3、 掌握增加设备驱动程序的方法。通过模块方法,增加一个新的设备驱动
程序,其功能可以简单。
实现字符设备的驱动;
4、 了解和掌握/proc 文件系统的特点和使用方法
了解/proc 文件的特点和使用方法
监控系统状态,显示系统中若干部件使用情况
用图形界面实现系统监控状态。
5、 设计并实现一个模拟的文件系统(选作)
三、 实验一
1、 编一个 C 程序,其内容为实现文件拷贝的功能
要实现文件拷贝功能,主要用到的函数是 open、write、read。
以前在 windows 下写 C 语言打开文件常用的 fopen,此时不能用,因
为 fopen 是 ANSIC 标准中的 C 语言库函数,在不同的系统中应该调用不
同的内核 api ;所以应该直接使用 linux 中的系统函数 open。
主要用到的头文件:
Unistd.h
Fcntl.h
Stdio.h
sys/types.h \\此头文件包含适当时应使用的多个基本派生类型
\\包含了许多 Linux 系统服务的函数原型,如:read、write
\\定义了很多宏和 open,fcntl 函数原型
\\标准输入输出头文件
sys/stat.h
\\包含了获取文件属性的一些函数
errno.h
string.h
\\用于调试错误代码是所需要的一些 errno 变量
\\包含了处理字符串的一些函数
设计思路:由命令行参数获取 2 个文件名,根据其文件名和路
径分别打开该 2 个文件,设置一个循环,从源文件复制 N 个字节到
目的文件,直到源文件指针到文件尾,最后关闭 2 个文件。
在可能出错的地方需要加上相应的报错代码和中断,并输出错
误信息,以方便调试或是往后应用在第 2 小题中可能发生的错误。
理清楚设计思路后,根据需求写出相应的源代码见后页源程序代码
scopy.c ;在 Linux 终端使用编译命令 gcc –o scopy scopy.c 将程序编译并
生产 exe 可执行文件。
然后手动创建一个测试文件 test.txt ,在终端输入命令
./scopy test.txt target.txt
这样就能将源文件 test.txt 复制到目标文件 target.txt
程序源代码 scopy.c:
#include
#include
#include
#include
#include
#include
#include
#define BUFFER_SIZE 1024
int main(int argc,char **argv)
{
int from_fd,to_fd;
int bytes_read,bytes_write;
char buffer[BUFFER_SIZE];
char *ptr;
if(argc!=3)
{
//三个参数
//缓冲区大小
//设定一个缓冲区
fprintf(stderr,"Usage:%s fromfile tofile\n\a",argv[0]);
return(-1);
}
/* 打开源文件 */
if((from_fd=open(argv[1],O_RDONLY))==-1)
{
fprintf(stderr,"Open %s Error:%s\n",argv[1],strerror(errno));
return(-1);
}
/* 创建目的文件 */
if((to_fd=open(argv[2],O_WRONLY|O_CREAT,S_IRUSR|S_IWUSR))==-1)
fprintf(stderr,"Open %s Error:%s\n",argv[2],strerror(errno));
return(-1);
{
}
while(bytes_read=read(from_fd,buffer,BUFFER_SIZE))
{
/* 出错*/
if((bytes_read==-1)&&(errno!=EINTR)) break;
else if(bytes_read>0)
{
ptr=buffer;
while(bytes_write=write(to_fd,ptr,bytes_read))
{
/* 出错*/
if((bytes_write==-1)&&(errno!=EINTR))break;
/* 写完了所有读的字节 */
else if(bytes_write==bytes_read) break;
/* 只写了一部分,继续写 */
else if(bytes_write>0)
{
}
ptr+=bytes_write;
bytes_read-=bytes_write;
}
/* 写的时候出错*/
if(bytes_write==-1)break;
}
}
close(from_fd);
close(to_fd);
return(1);
}
求用到 Linux 下的图形库。
安装 Linux 下的 GTK+:
2、 编一个 C 程序,其内容为分窗口同时显示三个并发进程的运行结果。要
首先要在 Linux 下载 GTK+相关库文件并安装。
在终端输入 sudo apt-get install gnome-core-devel ,然后根据提示操作,
就会安装 libgtk2.0-dev libglib2.0-dev 等开发所需的相关库文件。
$sudo apt-get install build-essential
$sudo apt-get install gnome-core-devel
$sudo apt-get install pkg-config
$sudo apt-get install libgtk2.0*
编译 GTK+代码时需要包含的头文件是 gtk/gtk.h,此外,还必须连接
若干库;比如编译 test.c 时用以下命令。
gcc –o test test.c `pkg-config --cflags --libs gtk+-2.0`
在编写代码时需要用到的控件、窗口等视窗物件形态,用类 GtkWidget
定义其为指针类型。
编写一个 GTK+程序的基本步骤如下:
初始化 Gtk
建立控件
登记消息与消息处理函数
执行消息循环函数 gtk_main()
之后所设计的 3 个进程,基本上都是以这样的方式编写代码的,因为
之前曾用过 OpenGL,所以在这方面掌握的比较快。
初始化主要使用的函数有
gtk_init(&argc,&argv);
gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_title(GTK_WINDOW(window),"标题名"); //设置窗口标
//启动 GTK
//创建窗口
题名
gtk_widget_set_usize(window, 200, 200);
gtk_widget_show(window);
//设置窗口大小
//显示窗口
建立控件的一般流程
/*创建表格准备封装*/
gtk_table_new (
gint rows,
gint columns,
//创建多少列
//创建多少栏
//用来决定表格如何来定大小
gint homogeneous);
/*这个函数是将表格 table,结合到窗口 window 里*/
gtk_container_add(GTK_CONTAINER(window),table);
gtk_widget_show(table); // 显示该表格
/*要把物件放进 box 中,可用以下函数*/
void gtk_table_attach_defaults (
GtkTable*table,
GtkWidget*widget,
gintleft_attach,
//参数("table")是选定某表格
//("child")是想放进去的物件
// 以 下 参数是指 定把物件 放在哪 里, 及用 多少个
boxes
gintright_attach,
ginttop_attach,
gintbottom_attach);
实验截图:
实验源代码:process.c:
#include
#include
#include
gint progress_timeout( gpointer pbar )
{
0.01;
if (new_val > 1.0)
new_val = 0.0;
gdouble new_val;
char s[10];
new_val = gtk_progress_bar_get_fraction (GTK_PROGRESS_BAR (pbar)) +
sprintf (s, "%.0f%%", new_val*100);
gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (pbar), new_val);
gtk_progress_bar_set_text (GTK_PROGRESS_BAR (pbar),s);
return TRUE;
}
void destroy_progress( GtkWidget *widget)
{
gtk_main_quit ();
}
void show(int argc,char *argv[],char *title )
{
GtkWidget *window;
GtkWidget *vbox;
GtkWidget *pbar;
GtkWidget *pbar2;
GtkWidget *button;
GtkWidget *label;
int timer;
char id_char[50];
gtk_init (&argc, &argv);
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_resizable (GTK_WINDOW (window), TRUE);
gtk_window_set_position(GTK_WINDOW(window),
GTK_WIN_POS_CENTER);
g_signal_connect
(destroy_progress), NULL);
(G_OBJECT (window),
"destroy", G_CALLBACK
gtk_window_set_title (GTK_WINDOW (window), title);
gtk_container_set_border_width (GTK_CONTAINER (window), 0);
vbox = gtk_vbox_new (FALSE, 10);
gtk_container_set_border_width (GTK_CONTAINER (vbox), 10);
gtk_container_add (GTK_CONTAINER (window), vbox);
gtk_widget_show (vbox);
sprintf (id_char, "本进程 ID:%d", getpid ());
label = gtk_label_new (id_char);
gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
gtk_widget_show (label);
sprintf (id_char, "父进程 ID:%d", getppid ());
label = gtk_label_new (id_char);
gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
gtk_widget_show (label);
pbar = gtk_progress_bar_new ();
gtk_box_pack_start (GTK_BOX (vbox), pbar, FALSE, FALSE, 0);
gtk_widget_show (pbar);
timer = gtk_timeout_add (100, progress_timeout, pbar);
button = gtk_button_new_with_label ("close");
g_signal_connect_swapped (G_OBJECT (button), "clicked", G_CALLBACK
(gtk_widget_destroy), window);
gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
gtk_widget_grab_default (button);
gtk_widget_show (button);
gtk_widget_show (window);
gtk_main ();
}
int main(int argc, char *argv[])
{
int pid = fork ();
if (pid < 0)
printf ("error!\n");
else if (pid == 0)
{
int pid = fork ();
if (pid < 0)
printf ("error!\n");
else if (pid == 0)
show (argc,argv,"process3");
else
show (argc,argv,"process2");
}