《Linux内核与程序设计》实验学习笔记

Linux内核与程序设计》实验指导

 

实验一  实验名称:常用命令和编辑器的使用(2学时)

 

一、实验目的

1、掌握Linux一般命令格式

2、掌握有关文件和目录操作的常用命令

3、掌握有关进程操作的常用命令

4、熟悉使用man命令

5、学习使用vi编辑器的建立、编辑、显示及加工处理文本文件

 

二、实验内容

1、熟悉date、cal、who、echo、clear、passwd命令

2、在用户主目录下对文件进行操作:复制一个文件、显示文件内容、查找指定内容、排序、文件比较、文件删除等

3、对目录进行管理:创建和删除子目录、改变和现实工作目录、列出和更改文件权限、链接文件等

4、利用man显示date、echo等命令的手册页

5、利用文本插入方式建立一个文件

6、对该文件执行删除、复原、修改、替换等操作

三、主要实验步骤

1、使用简单命令date、cal、who、echo、clear、passwd等,了解linux命令格式


输入date会显示当前日期

输入cal会显示日历

who:显示用户

clear 清屏

passwd 更换用户密码



2、浏览文件系统:

(1)运行pwd命令,确定当前工作目录


pwd:输出当前目录

(3)运行ls –ai命令,理解各字段含义


ls  :列出当前目录下的文件和文件夹,不包括隐藏文件

ls -l:显示当前目录下文件或者文件夹的详细信息

ls -a:列出当前目录下的文件和文件夹,包括隐藏文件 

ls -i:列出当前目录下的文件和文件夹,并显示其index

ls -ai:列出当前目录下的文件和文件夹,包括隐藏文件,并显示其index



(4)使用cd命令,将工作目录改为根(/)上,运行ls –l命令,结合书中图2.2,了解个目录的作用


/表示根目录

cd  /即可


(5)直接使用cd,回到哪里了?用pwd验证


答案是:/home/ysk,即用户目录


(6)用mkdir建立一个子目录subdir


创建子目录:mkdir subdir


(7)将工作目录改到subdir


在 /home/ysk 下输入命令 cd subdir

定位为 /home/ysk/subdir


3、工作操作

(1) 验证当前工作目录在subdir

(2) 运行date>file1,然后运行cat file1,看到什么信息?


cat file1 是将file1文件中的内容显示到屏幕上

date>file1 是将当前时间输出入道file1中


(3) 运行cat subdir,会有什么结果?为什么?

cat: subdir: Is a directory


(4) 利用man命令显示date命令的使用说明


man date

4、运行man date>>file1,看到什么?


追加进入file1


运行cat file1,看到什么?

显示 file1 内的内容


5.文件操作

(1)显示file1的前10行,后10行


 head -10 file1

 tail -10 file1

(2)运行cp file file2,然后ls –l,看到什么

凭空多出了file2呗,内容与file完全相同


(3)运行cat f*,结果怎样


输出f开头文件的内容?


(4)运行rm file3,然后ls –l,结果如何


删了


(5)统计file1文件的行数、字数

cat file1|wc -l


6.vi编辑器

    (1)进入vi

    (2)建立一个文件,如file.c.进入插入方式,输入一个C语言程序的各行内容,故意制造几处错误.最后,将该文件存盘.回到shell状态下.

    (3)运行gcc file.c –o myfile,编译文件,会发现错误提示.理解其含义

    (4)重新进入vi,对该文件进行修改.然后存盘,退出vi.重新编译该文件.如果编译通过了,可以用./myfile运行该程序

    (5)运行mandate>file10,然后vi file10。

       使用x,dd等命令删除某些文本行。

       使用u命令复原此前的情况。

       使用c、r、s等命令修改文本内容。

       使用检索命令进行给定模式的检索。

 


在vi编辑器中调大字体 ctrl+shift+'+'

在vi编辑器中减小字体 ctrl+'-'


linux退出vi编辑器的方法
 
对于vi编辑器而言,输入i是插入状态。
 
如果要退出的话,先按esc键,然后输入冒号(:),

再输入wq是保存且退出,输入q!不保存退出。


在某个一行按 数字+yy 可以复制指定数字的行,然后按p粘贴

u 撤销

ctrl+r 恢复上一步的操作                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 

实验二 实验名称:shell脚本的设计和执行(2学时)

 

一、实验目的

1.  了解shell的作用和主要分类

2.  掌握shell脚本的建立和执行方式

3.  掌握编写shell脚本的基本语法

4.  学会编写并执行shell脚本

 

二、实验内容

1.  历史命令和别名定义

2.  shell脚本的建立和执行

3.  shell变量和位置参数、环境变量

4.  shell特殊字符在脚本中的使用

5.  一般控制结构的使用

6.  算数运算和函数的使用

 

三、主要实验步骤

1.  利用vi编辑器建立一个简单的shell脚本,其中包括date,pwd,ls等常用命令。然后以至少两种不同的方式执行该脚本(参考书上P84,4.1.3节内容)。

[ysk@localhost ~]$ cat aaa
echo hello,world
echo "hello,world2"




[ysk@localhost ~]$ bash<aaa
hello,world
hello,world2
[ysk@localhost ~]$ 



2.  运行history命令,查看历史命令环境;

[ysk@localhost ~]$ history


3.  体会命令补齐功能(参见4.3节内容);

[ysk@192 ~]$ cat ex
ex       ex11~    ex14     ex2      ex4      exam12~  exp1     
ex~      ex12     ex17     ex2~     ex4~     exam13   
ex11     ex13     ex17~    ex3      exam12   exam13~  
[ysk@192 ~]$ cat ex


按下tab+tab 或者esc+ '?'


4.  编辑并运行书上P91页4.5.2节引号的相关脚本和命令;


[ysk@192 ~]$ cat ex
echo "current directory is `pwd`"
echo "home directory is $HOME"
echo "file*.?"
echo "directory ‘$HOME’ "
echo  directory ‘$HOME’


[ysk@192 ~]$ ./ex
current directory is /home/ysk
home directory is /home/ysk
file*.?
directory ‘/home/ysk’ 
directory ‘/home/ysk’
[ysk@192 ~]$ 


5.  编辑并运行书上P108页例4.9,体会位置参数的相关用法;

echo $0 $1 $2 $3 $4 $5 $6 $7 $8 $9
shift
echo $0 $1 $2 $3 $4 $5 $6 $7 $8 $9
shift 4
echo $0 $1 $2 $3 $4 $5 $6 $7 $8 $9


[ysk@localhost ~]$ ./ysk_1 A B C D E F G H I J K
./ysk_1 A B C D E F G H I
./ysk_1 B C D E F G H I J
./ysk_1 F G H I J K


6.  编辑并运行书上P125页,例4.13,体会shell脚本中条件表达式、算数表达式、逻辑运算的使用方法,同时需要注意实验室linux环境与书本中linux版本的不一致;


ysk_2:


f [ 3 -gt 2 ]
then
        echo "3>2"
else
        echo "3<=2"
fi


[ysk@localhost ~]$ ./ysk_2
3>2


if [[ 3 -gt 2 ]]
then
	echo "3>2"
else
	echo "3<=2"
fi


[ysk@localhost ~]$ ./ysk_2
3>2


[[后面要留出一个空格 

]]前面也要留出一个空格


f [ 3 -lt 2 -o 3 -gt 2  ]
then
        echo "true"
else
        echo "false"
fi

[ysk@localhost ~]$ ./ysk_2
true


不能把里面的-o 写成||

否则结果是false




7.  编辑并运行书上P130页,例4.15,体会值表方式的for循环与位置参数相结合的使用方法;

dir=$1;shift
if [ -d $dir ]
then
	cd $dir
	for name
	do
		if [ -f $name ]
		then cat $name
			echo "End of ${dir}/$name"
		else
			echo "Invalid file name: ${dir}/$name"
		fi
	done
else echo "Bad directory name:$dir"
fi

[ysk@192 ~]$ ./ex144 code 111 222
#echo "sa"
echo "sa"
End of code/111
if test -f "$1"
then echo "$1 is a file"
else echo "$1 is not a file"
fi

End of code/222
[ysk@192 ~]$ 


if和[之间需要有空格


[ test -d $dir ] 好像不行 [ -d $dir ]可以


8.  编辑并运行书上P131页,例4.16,体会算数表达式方式的for循环用法;

for((i=1;i<=$1;i++))
do
	for((j=1;j<=i;j++))
	do
		echo -n "*"
	done
	echo ""
done
echo "end!"

[ysk@192 ~]$ ./ex145 4
*
**
***
****
end!
[ysk@192 ~]$ 



9.  编辑并运行书上P134页,例4.19,体会shell脚本中函数的使用;


func()
{
	echo "Let's begin now."
	echo $a $b $c
	echo $1 $2 $3
	echo "The end."
}
a="Working directory"
b="is"
c=`pwd`
func Welcome You Byby
echo "Today is `date`"


[ysk@192 ~]$ chmod a+x ex146
[ysk@192 ~]$ ./ex146
Let's begin now.
Working directory is /home/ysk
Welcome You Byby
The end.
Today is Sun Apr 16 04:17:01 PDT 2017
[ysk@192 ~]$ 



10.自己编写shell脚本,实现以下功能:

11.Shell脚本文件名为sq,执行时接受2-10范围内的一个整数作为输入参数,在屏幕上用+号、@号和 &号画出以给定参数为边长的正方形。

&特殊字符 echo时需要加引号" "或' '

12.例如:输入命令$ sq 4并回车,则屏幕上会绘制如下的正方形,(注:其中第2、3行上的&符号之间有两个空格)

@++@

&   &

&   &

@++@


read x
if  [ $x -lt 2 -o $x -gt 10 ]
	then 
	echo "x must in [2,10]"
	exit
fi
echo -n @
for((i=1;i<=$x-2;i++))
do
	echo -n +
done
echo @


for((i=1;i<=$x-2; i++))
do
	echo -n '&'
	for((j=1;j<=$x-2;j++))
	do
		echo -n " "
	done
	echo    "&"
done

echo -n @
for((i=1;i<=$x-2;i++))
do
        echo -n +
done
echo @


[ysk@192 ~]$ ./t2_10 
4
@++@
&  &
&  &
@++@
[ysk@192 ~]$ ./t2_10
12
x must in [2,10]
[ysk@192 ~]$ ./t2_10
6
@++++@
&    &
&    &
&    &
&    &
@++++@
[ysk@192 ~]$ 


 

实验报告要求:在实验步骤中写出主要的脚本代码,并且最后要写实验小结

 




实验三 实验名称: Linux环境下程序的编译和调试(2学时)

 

一、实验目的

1、 掌握gcc编译器在预处理、编译、汇编和连接各个阶段的用法

2、 掌握gdb调试工具的常用命令

 

二、实验内容

1.   使用gcc编译器中的预处理选项

2.   使用gcc编译器中的编译程序选项

3.   使用gdb调试工具的使用

 

三、实验步骤

1.   编写并验证书本P180页例题6.1

hello.c

#include<testI.h>
#define fatal "!!!!!!"


main()
{
	printf("display -D variable %s\n",DOPTION);
	printf("display overwrite fatal=%s\n",fatal);
	printf("Hello ,everybody!!\n");
}

testI.h

#define fatal "please call Lawrence for help"


[ysk@localhost ~]$ gcc -I ./tmp -D DOPTION='"testing -D" ' -D fatal -E hello.c
# 1 "hello.c"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "hello.c"
# 1 "./tmp/testI.h" 1
In file included from hello.c:1:
./tmp/testI.h:1:1: warning: "fatal" redefined
<command-line>: warning: this is the location of the previous definition
# 2 "hello.c" 2
hello.c:2:1: warning: "fatal" redefined
./tmp/testI.h:1:1: warning: this is the location of the previous definition






main()
{
 printf("display -D variable %s\n","testing -D");
 printf("display overwrite fatal=%s\n","!!!!!!");
 printf("Hello ,everybody!!\n");
}
[ysk@localhost ~]$ 


出现了重复的宏定义,如果都没有相关的定义那么 -D fatal 后 fatal的值为1


//#include<testI.h>
#define fatal "please call Lawrence for help"


main()
{
	printf("display -D variable %s\n","testing -D");
	printf("display overwrite fatal=%s\n","please call Lawrence for help");
	printf("Hello ,everybody!!\n");
}


控制台:

[ysk@localhost ~]$ gcc -D DOPTION=' "testing -D"' hello.c
hello.c: In function ‘main’:
hello.c:7: warning: incompatible implicit declaration of built-in function ‘printf’
[ysk@localhost ~]$ ./a.out
display -D variable testing -D
display overwrite fatal=please call Lawrence for help
Hello ,everybody!!



[ysk@localhost ~]$ gcc -D DOPTION=' "testing -D"' hello.c
hello.c: In function ‘main’:
hello.c:7: warning: incompatible implicit declaration of built-in function ‘printf’
[ysk@localhost ~]$ ./a.out
display -D variable testing -D
display overwrite fatal=please call Lawrence for help
Hello ,everybody!!



2.   编写并验证书本P181页例题6.2

#include <stdio.h>
int  main()
{
	int r;
	printf("Enter an integer,please!\n");
	scanf("%d",&r);
	square(r);
	return 0; 
}

#include<stdio.h>

int square(int x)
{
	
	printf("The square=%d\n",x*x);
	return 0;
}

此时直接gcc  meng1.c或者gcc meng2.c貌似是不可以的

正确的做法:

[ysk@localhost ~]$ gcc -c meng2.c
[ysk@localhost ~]$ gcc meng1.o meng2.o -o meng12
[ysk@localhost ~]$ ./meng12
Enter an integer,please!
2
The square=4



3.   编写并验证书本P193页6.2.6应用示例

 



第四章的一些知识点:


1.关于将路径添加到环境变量PATH

[ysk@192 ~]$ ./aaa
hello,world
hello,world2
[ysk@192 ~]$ PATH=$PATH:./
[ysk@192 ~]$ aaa
hello,world
hello,world2


也就是说在当前(任意)文件夹,不用再./xxx执行文件,而是可以直接用文件名执行。


2.将变量送入进程转出区

sd


exam12:


major=“English”
echo “His major is $major”

exam13:


echo “her major is $major”



[ysk@192 ~]$ exam12
bash: ./exam12: Permission denied
[ysk@192 ~]$ chmod a+x exam12
[ysk@192 ~]$ chmod a+x exam13
[ysk@192 ~]$ exam13
“her major is ”
[ysk@192 ~]$ exam12
“His major is “English””
[ysk@192 ~]$ major="computer science"
[ysk@192 ~]$ export major
[ysk@192 ~]$ exam12
“His major is “English””
[ysk@192 ~]$ exam13
“her major is computer science”

 

3.只有使用 $((算术表达式))的形式才能返回表达式的值


[ysk@192 code]$ echo "(12*9)"
(12*9)
[ysk@192 code]$ echo (12*9)
bash: syntax error near unexpected token `12*9'
[ysk@192 code]$ echo "((12*9))"
((12*9))
[ysk@192 code]$ echo ((12*9))
bash: syntax error near unexpected token `('
[ysk@192 code]$ echo "$((12*9))"
108
[ysk@192 code]$ echo $(12*9)
bash: 12*9: command not found

[ysk@192 code]$ echo $((12*9))
108


[ysk@192 code]$ let "i=2*3"
[ysk@192 code]$ i
bash: i: command not found
[ysk@192 code]$ $i
bash: 6: command not found
[ysk@192 code]$ echo $i
6
[ysk@192 code]$ echo "$i"
6

[ysk@192 code]$ let "i=2*3"
[ysk@192 code]$ i
bash: i: command not found
[ysk@192 code]$ $i
bash: 6: command not found
[ysk@192 code]$ echo $i
6
[ysk@192 code]$ echo "$i"
6
[ysk@192 code]$ ((j=i*2))
[ysk@192 code]$ echo $j
12
[ysk@192 code]$ echo "$j"
12



4.test -f 文件名



222:

if test -f "$1"
	then echo "$1 is a file"
	else echo "$1 is not a file"
fi
	

[ysk@192 code]$ 
333
23
x
23
[ysk@192 code]$ chmod a+x 222
[ysk@192 code]$ 222
 is not a file
[ysk@192 code]$ 222 222
222 is a file
[ysk@192 code]$ 222 111
111 is a file
[ysk@192 code]$ ^C
[ysk@192 code]$ 222 aaa
aaa is not a file




ex14:

read k
echo $k 
((k=k-1))
let "i=k+1"
echo $k
echo $i





[ysk@192 ~]$ ./ex14
4
4
3
4




5.read /echo


333:

read x
echo x
echo $x



[ysk@192 code]$ 
333
23
x
23


6.case的用法

444:

read x
case $x in
1) echo x=1;;
2) echo x=2;;
esac

case $x 后面要加in,然后不用打:之类的

然后是一系列的),)前面是匹配的值,后面是操作,记得要打;;

将case倒过来写esac来结束



[ysk@192 code]$ 444
1
x=1
[ysk@192 code]$ 444
2
x=2
[ysk@192 code]$ 444
3



555:

[ysk@192 code]$ chmod a+x 555
[ysk@192 code]$ 555
1
x=1
[ysk@192 code]$ 555
2
x=2
[ysk@192 code]$ 555
3


read x
case $x in
1) 
echo x=1
;;
2)
echo x=2
;;
esac




7.

ex11

echo –n "Type in a number (1-10)"
read num
   if  [  "$num" -lt 1 -o "$num" -gt 10 ]
        then echo "Error input"
             exit 2
   elif [ ! "$num" -lt 5 ]
        then echo "it is not less 5"
             else echo "it is less 5"
    fi
echo "accept number in value"
  


[ysk@192 ~]$ ./ex11
–n Type in a number (1-10)
5
it is not less 5
accept number in value
[ysk@192 ~]$ ./ex11
–n Type in a number (1-10)
12
Error input


不知为何双中括号 [[ ]]一直不行 

[[ ]]中要用||和&&来表示-o -a


for((i=1;i<=5;i++))
do
	echo $i
done

[ysk@192 ~]$ ./ex12
1
2
3
4
5


8. while


ex13:

read k
while [ "$k" -gt 0 ]
do
        echo $k
        ((k=k-1))
done



[ysk@192 ~]$ ./ex13
4
4
3
2
1



9.函数


还没研究清楚:

function valtest()
{
       echo "Begin to test how to pass values"
       echo $a $b $c
       echo $1 $2 $3 $4
       echo "The end of function valtest"
	return 1
}
       a="current working directory"
       b="is"
       c=`pwd`
       valtest Let's begin to use Linux
##      k=$(( valtest Let's begin to use Linux )) 
       echo "Today is `date`"
##       echo $k


实验四 实验名称:Linux进程控制程序的设计和实现(2学时)

 

一、实验目的

1、 理解系统调用和库函数的使用方法和格式

2、 掌握文件操作相关的系统调用函数的使用和编程

3、 掌握进程控制相关的系统调用函数的原理、语法和编程应用

 

二、实验内容

1.   使用文件操作系统调用函数open,read,write进行程序设计

2.   创建子进程的系统调用fork()设计程序,观察程序的执行结果

3.   比较子进程等待函数wait和waitpid的异同

 

三、实验步骤

1.编辑并运行下列代码,理解fork函数的执行原理

int main()

{ int i;

  int pid;

  pid=fork();

  if (pid<0) printf(“error”)

  else if (pid == 0)

 {   for (i = 1; i < 3; i++)

        printf("This is child process\n");

  }

  else

 {   for (i = 1; i < 3; i++)

     printf("This is parent process\n");

  }

}


#include<stdio.h>


int main()
{
  int i;
  int pid;
  pid=fork(); 
  if (pid<0) printf("error");
  else if (pid == 0)
  {
       for (i = 1; i < 3; i++)
        printf("This is child process\n"); 
  } 
  else
  {
     for (i = 1; i < 3; i++) 
     printf("This is parent process\n");
  } 
  return  0;
}   



[ysk@localhost ~]$ vi c1.c
[ysk@localhost ~]$ gcc c1.c-o ec1
gcc: c1.c-o: No such file or directory
[ysk@localhost ~]$ gcc c1.c -o ec1
[ysk@localhost ~]$ ec1
This is parent process
This is parent process
[ysk@localhost ~]$ This is child process
This is child process
vi c1.c
[ysk@localhost ~]$ ec1
This is parent process
This is parent process
[ysk@localhost ~]$ This is child process
This is child process



 

2.编辑并执行下列程序,观察并分析程序执行结果

int com=0;
main()
{
    pid_t pid;
    pid=fork();

    if(pid<0)
      then printf("error");
    else if(pid==0)
      then
          {com=1};
      else
          {com=com+1};
   

   printf{"com=%d\n",com};
}

 

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>

int com=0;
int main()
{
    pid_t pid;
    pid=fork();

    if(pid<0)  printf("error");
    else if(pid==0)  com=1;
    else   com=com+1;

    printf("com=%d\n",com);

    return 0;
}


[ysk@localhost ~]$ vi c2.c
[ysk@localhost ~]$ gcc c2.c -o ec2
[ysk@localhost ~]$ ec2
com=1
[ysk@localhost ~]$ com=1
ec2
com=1
[ysk@localhost ~]$ com=1


3.编辑并执行下列程序,观察并分析进程ID获取函数的用法

#include <unistd.h>
#include <sys/types.h>
main()
{
   pid_t pid; 
   pid=fork();
  if(pid<0) printf("fork error!\t");
   else if(pid==0)
 printf("child process now! pid=%d ppid=%d\t",getpid(),getppid());

          elseprintf("parent process now! pid=%d child_pid=%d\t",getpid(),pid);
}    

 


#include <unistd.h>
#include <sys/types.h> 
#include <stdio.h>
int main() 
{ 
   pid_t pid; 
   pid=fork(); 
   if(pid<0) printf("fork error!\n"); 
   else if(pid==0) 
   printf("child process now! pid=%d ppid=%d\n",getpid(),getppid());

   else
   printf("parent process now! pid=%d child_pid=%d\n",getpid(),pid);
   return 0;
}  


[ysk@192 ~]$ ./ec3
parent process now! pid=2692 child_pid=2693
[ysk@192 ~]$ child process now! pid=2693 ppid=1


因为用fork函数创建子进程,父进程没有等待子进程的退出,这可能导致子进程编程孤儿进程,被init进程接管,所以父进程id为1


4. 编写程序验证书本P213页的例题7.3

 


#include <unistd.h>
#include <sys/types.h>
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>

int main(int argc,char **argv)
{
	pid_t pid,old_ppid,new_ppid;
	pid_t child,parent;

	parent=getpid();
	if((child=fork())<0)
	{

  	  fprintf(stderr,"%s:fork of child failed:%s\n",argv[0],strerror(errno)	);
	  exit(1);	
 	}
	else if(child==0)
	{
	    old_ppid=getppid();
	    sleep(2);
	   new_ppid=getppid();
	}
	else
	{
		sleep(1);
		exit(0);
	}

	printf("Original parent:%d\n",parent);
	printf("Child:%d\n",getpid());
	printf("Child's old ppid:%d\n",old_ppid);
	printf("Child's new ppid:%d\n",new_ppid);
	exit(0);
}


gcc c4.c -o ec4
[ysk@192 ~]$ ./ec4
[ysk@192 ~]$ Original parent:2759
Child:2760
Child's old ppid:2759
Child's new ppid:1
./ec4
[ysk@192 ~]$ Original parent:2761
Child:2762
Child's old ppid:2761
Child's new ppid:1





5.编写程序验证PPT中的相关例题,思考运行结果。

 

 

实验五 实验名称:Linux进程通信的程序设计和实现(2学时)

 

一、实验目的

1、 掌握进程通信相关的系统调用的语法格式

2、 掌握pipe,kill和消息队列函数在父子进程通信时的具体用法

3、 能够读、写系统调用程序,理解程序的输出结果。

 

二、实验内容

1.   在程序设计中使用pipe函数进行基于管道的进程通信

2.   在程序设计中使用kill函数进行基于信号量的进行通信

3.   在程序设计中使用消息队列机制实现进行通信

 

三、实验步骤

 

1.参考下列伪码,编辑并执行pipe函数的程序

#include<unistd.h>

#include<stdio.h>

#include<errno.h>

int main(intargc,char **argv)

{

    static const char mesg[]="Happy NewYear";

    char buf[BUFSIZ];

    size_t rcount,wcount;

    int p_fd[2];

    size_t n;

 

    if(pipe(p_fd)<0){

        printf(“pipe error”);

        exit(EXIT_FAILURE);

    }

    printf("Read end=fd %d,write end=fd%d\n",p_fd[0],p_fd[1]);

    n=strlen(mesg);   

if((wcount=write(p_fd[1],mesg,n))!=n){

       printf(“write error”);

        exit(EXIT_FAILURE);

    }

   if((rcount=read(p_fd[0],buf,BUFSIZ))!=wcount){

        printf(“read error”);

        exit(EXIT_FAILURE);

    }

    printf("Read <%s>from pipe\n",buf);

    close(p_fd[0]);

    close(p_fd[1]);

    return 0;

}

 

#include<unistd.h>
#include<stdio.h>
#include<errno.h>
#include<stdlib.h>
#include<string.h>

int main(int argc,char **argv)

{

    static const char mesg[]="Happy NewYear";

    char buf[BUFSIZ];

    size_t rcount,wcount;

    int p_fd[2];

    size_t n;

 

    if(pipe(p_fd)<0){

        printf("pipe error");

        exit(EXIT_FAILURE);

    }

    printf("Read end=fd %d,write end=fd %d\n",p_fd[0],p_fd[1]);

    n=strlen(mesg);   

if((wcount=write(p_fd[1],mesg,n))!=n){

       printf("write error");

        exit(EXIT_FAILURE);

    }

   if((rcount=read(p_fd[0],buf,BUFSIZ))!=wcount){

        printf("read error");

        exit(EXIT_FAILURE);

    }

    printf("Read <%s>from pipe\n",buf);

    close(p_fd[0]);

    close(p_fd[1]);

    return 0;

}


[ysk@localhost ~]$ ./sy5_1e
Read end=fd 3,write end=fd 4
Read <Happy NewYear>from pipe
[ysk@localhost ~]$ 


2.在下列伪码中加入头文件,编辑运行,理解kill函数

int main()

{ pid_tchild;

   int status, retval;

   if((child=fork())<0) {perror(“fork”);  exit(EXIT_FAILURE); }

   else if (child==0) {

      printf(“Child’s ID:%d\n”, child);

      sleep(20);

      exit(0); }

      else {

        if((waitpid(child,&status,WNOHANG))==0){

               retval=kill(child,SIGKILL);

               if (retval){

                   perror(“kill”);

                   waitpid(child,&status,0);

               }

               else printf(“%d iskilled”,child);

      }

}                 

 

#include<unistd.h>
#include<stdio.h>
#include<errno.h>
#include<stdlib.h>
#include<string.h>
#include<signal.h>

int main()
{ 
   pid_t child;
   int status, retval;

   if((child=fork())<0) 
   {
	perror("fork");  exit(EXIT_FAILURE); 
   }
   else if (child==0) 
   {
      printf("Child's ID:%d\n", child);
      sleep(20);
      exit(0);  
   }
   else 
    {
	
        if( (waitpid(child,&status,WNOHANG) )==0)
	 {
               retval=kill(child,SIGKILL);
               if (retval)
		{
                   perror("kill");

                   waitpid(child,&status,0);
                }
               else printf("%d is killed\n",child);
         }

     }

     return 0;
}                 

[ysk@localhost ~]$ ./sy5_2e
2448 is killed
[ysk@localhost ~]$ 







3.编辑并运行书本P218页进程使用消息队列进行通信的例题。思考消息队列的使用机制和运作机制。

 



#include<unistd.h>
#include<sys/types.h>
#include<sys/ipc.h>
#include<sys/msg.h>
#include<stdio.h>//5
#include<stdlib.h>
#include<string.h>
#define BUFSZ 512
struct msg
{//10
	long type;
	char text[BUFSZ];
};

int main(void)//15
{
	int qid;
	key_t key;
	int len1,len2;
	struct msg pmsg_w,pmsg_r;//20
	
	key=IPC_PRIVATE;
	if( (qid=msgget(key,IPC_CREAT|0666 ) )<0 )
	{
		perror("msgget:create");//25
		exit(EXIT_FAILURE);
	}
	puts("Enter message to past");
	if(fgets(pmsg_w.text,BUFSZ,stdin)==NULL)
	{//30
		puts("Wrong,no message to post.");
		exit(EXIT_FAILURE);
	}
	pmsg_w.type=10;
	len1=strlen(pmsg_w.text);//35
	if(msgsnd(qid,&pmsg_w,len1,IPC_NOWAIT )<0)
	{
		perror("msgsnd");
		exit(EXIT_FAILURE);
	}//40
	puts("message posted.");
	puts("***************");

	len2=msgrcv(qid,&pmsg_r,BUFSZ,10,IPC_NOWAIT|MSG_NOERROR);
	if(len2>0)//45
	{
		pmsg_r.text[len2]='\0';
		printf("reading queue id=%05d\n",qid);
		printf("message type=%05ld\n",pmsg_r.type);
		printf("message length=%d bytes\n",len2);//50
		printf("message text=%s\n",pmsg_r.text);
	}
	else
	{
		perror("msgrcv");
		exit(EXIT_FAILURE);
	}
	exit(EXIT_SUCCESS);
}


[ysk@localhost ~]$ ./sy5_3e
Enter message to past
Happy New Year!
message posted.
***************
reading queue id=131076
message type=00010
message length=16 bytes
message text=Happy New Year!


[ysk@localhost ~]$ 

4.编辑并运行书本P220页例题7.7, 思考和验证运行结果。

 

#include<unistd.h>
#include<sys/types.h>
#include<wait.h>
#include<signal.h>
#include<stdio.h>//5
#include<stdlib.h>

int main()
{
	pid_t pid;//10
	int num;
	if( (pid=fork())<0 ) 
	{
		perror("fork");
		exit(EXIT_FAILURE);//15
	}
	else if(pid==0)
	{
		sleep(30);
	}//20
	else
	{
		printf("Sending SIGCHLD to %d\n",pid);
		num=kill(pid,SIGCHLD);
		if(num<0)//25
			perror("kill:SIGCHLD");
		else 
			printf("%d still alive\n",pid);
		printf("Killing %d\n",pid);
		if( (kill(pid,SIGTERM) )<0  )
			perror("kill:SIGTERM");
		waitpid(pid,NULL,0);
		
	}
	exit(EXIT_SUCCESS);
}



[ysk@localhost ~]$ ./sy5_4e
Sending SIGCHLD to 3100
3100 still alive
Killing 3100
[ysk@localhost ~]$ 

5.编写程序验证PPT中的相关例题,思考运行结果。

 


[ysk@192 code]$ 
333
23
x
23
  • 8
    点赞
  • 47
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是关于《Linux内核设计与实现》的笔记: 1. 进程管理 - 进程控制块(Process Control Block, PCB):一个进程在内核中的表示,包含了进程的状态、各种计数器和指针,以及进程所需要的资源。 - 进程调度:内核必须在可能的情况下公平地分配CPU时间片给每个进程。Linux内核使用完全公平调度(Completely Fair Scheduler, CFS)来实现这一点。 - 进程同步:进程在访问共享资源时需要同步,以避免冲突。Linux内核提供了多种同步机制,如信号量、自旋锁和读写锁等。 2. 内存管理 - 虚拟内存:每个进程都拥有自己的虚拟内存空间,这使得每个进程都可以认为自己独占整个系统内存。 - 页面置换:当物理内存不足时,Linux内核使用页面置换算法将一部分未使用的页面从物理内存中移出,以便为正在运行的进程腾出空间。 - 内存映射文件:Linux允许将磁盘上的文件映射到进程的虚拟地址空间中,这样就可以像访问内存一样访问文件。 3. 文件系统 - 虚拟文件系统(Virtual File System, VFS):Linux内核中的抽象层,它允许系统支持多种文件系统格式,如ext4、FAT32等。 - I/O管理:内核必须管理所有的I/O操作,包括磁盘读写和网络通信等。 - 文件描述符:Linux内核使用文件描述符来标识打开的文件,每个进程都有一个文件描述符表。 4. 网络协议栈 - TCP/IP协议栈:Linux内核支持多种网络协议,其中最常用的是TCP/IP协议栈。 - Socket:在Linux中,进程之间通信的主要方式是使用Socket。Socket是一种抽象的概念,它代表了一个网络连接。 5. 设备驱动程序 - 驱动程序开发:Linux内核的设备驱动程序通常是以模块的形式开发的,它们可以动态地加载和卸载。 - 设备文件:Linux内核将设备表示为文件,它们可以通过文件系统接口来访问。 以上是《Linux内核设计与实现》的一些重点内容和笔记,希望对你有所帮助。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值