计算机操作系统教程实验
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
void P(int semid,int index) //对标记符为semid的信号量集 中的第index个 //元素进行P操作(信号量操作要用到semop()函数) { struct sembuf sem; //此数据类型在sys/sem.h中定义 sem.sem_num = index;//对信号量集中的第index个元素进行P操作 sem.sem_op = -1; //表示P操作 sem.sem_flg = 0; //操作标记:0或IPC_NOWAIT等 semop(semid,&sem,1); //1:要操作1个信号量 }
void *subp1()//计算线程 { int i; for (i=0;i<LOOPS;i++) { P(semid,0); a+=10; V(semid,1); } return; }
void *subp2()//打印线程 { int i,j; for (i=0; i< LOOPS;i++) { P(semid,1); printf("subp1:a=%d\n",a); V(semid,0); } return; }
一个简单的线程创建程序
#include<stdio.h> #include<sys/types.h> #include<pthread.h> int
data; void sub1(void) { data += 1; printf("SubThread-->data=%d\n",data); } int main(void) { data = 4; pthread_t pthread1; pthread_create(&pthread1,NULL,(void*)sub1,NULL); pthread_join(pthread1,NULL); data += 1; printf("MainThread -->data=%d\n",data); return 0; }
信号量(集)的创建:
使用系统调用semget()创建一个新的信号量集,或者存取一 个已经存在的信号量集. 原型:int semget(key_t key,int nsems,int semflg) 返回值:若成功,则返回信号量集的IPC标识符;失败返回-1. 参数:key:一般取ftok()函数返回值或一个整型常量 nsems:信号灯的个数 semflg:通常取值为IPC_CREAT | 0666 示例:int semid = semget(300,2,IPC_CREAT | 0666)
利用GCC编译器编译程序得到目标文件 gcc fileName [-o executableFileName] [-lpthread] 执行目标文件: ./executableFileName 说明: 动态链接库libpthread.so不是Linux默认的库,所以在进 行链接的时候需要将其导入(通过-lpthread)
#include<stdio.h> #include<sys/types.h> #include<unistd.h> int main(void) { pid_t pid ; int data = 4; if(0==(pid=fork()))//子进程 { data += 1; printf("SubProcess : %d\n ",data);
显示当前工作目录:pwd 文件相关操作:
ls: 显示文件信息 [-l;-a;-i;] cp: 拷贝文件 [-r] mv: 移动文件 touch: 创建文件 rm: 删除文件 [-rf ] mkdir: 新建文件夹 rmdir: 删除空白文件夹 cd: 切换工作目录 cd - ; cd ~; cd; chmod: 更改文件权限 chown: 更改文件所属用户及用户组 cat 、more 、less、 head 、tail:显示文件内容 ln [-s] 源路径 目标路径 返回
实验一、二:进(线)程同步与通信
一、实验名称 实验一、计算/打印进(线)程的同步 实验二、誊抄问题的进(线)程解法
二、实验目的
1、掌握Linux系统用户界面中键盘命令的使用;
2、熟悉Linux下的编程环境; 3、理解Linux下进(线)程的概念及其区别; 4、了解Linux进程同步与通信的主要机制,并通过 信号灯操作实现进程间的同步与互斥。
//资源empty初始化为1 semopts.val = 1; res=semctl(semid,0,SETVAL,semopts); //资源data初始化为0 semopts.val = 0; res=semctl(semid,1,SETVAL,semopts);
返回
线程
1)线程创建
int pthread_create( pthread_t *thread, pthread_attr_t *attr, void *(*start_routine)(void *),void *arg ); 返回值:成功-返回0,失败-返回错误编号
gg ;G; nG; w;e;b;h;j;k;l;
VI模式转换(续)
命令模式---->末行模式
方式:在命令态按 ‘:’ 或 ‘/’ 末行模式下的常见命令:
(1)
(2)
列出行号 取消行号 存盘 存盘退ห้องสมุดไป่ตู้ 强制退出 寻找字串
:set nu :set nonu :w :wq :q! (不保存修改) /word (由首至尾寻找)
VI模式转换
命令模式---->插入模式 i :插入, 从目前光标所在之处插入所输入之文字。I a :增加, 目前光标所在之下一个字开始输入文字。A o :从新的一行行首开始输入文字。 O 命令模式下常用命令: x :删除一个文字。 dd :删除光标所在之行。 yy:复制当前行。 pp:粘贴。 X ndd nyy npp
Linux文件编辑器VI
什么是Vi:Linux古老但功能强大的全屏幕编辑器
Vi的启动方式:
--$vi 文件名 打开已有的文件或编辑新文件
--$vi
先编辑,以后命名存盘
VI的模式
Vi的三种模式 命令模式 :使用编辑命令; 插入模式 :做文字输入; 末行模式 :离开编辑器,或者设置编辑环境, 如寻找字串、列出行号等。
} else//父进程 {
exit(0);
wait(NULL);//或者waitpid(pid,NULL);
}
} return 0;
data += 2; printf("MainProcess : %d\n",data);
//wait:只要有一个子进程返回,父进程就继续执行 //waitpid:只有当pid返回时,父进程才返回;
IPC_RMID: 将信号量集从内存中删除;
示例: 初始化信号量集:arg.val=1;semctl(semid,1,SETVAL,arg)
删除信号量集:semctl(semid,0,IPC_RMID);
示例:
union semun { int val; /* Value for SETVAL */ struct semid_ds *buf; /* Buffer for IPC_STAT, IPC_SET */ unsigned short *array; /* Array for GETALL, SETALL */ struct seminfo *__buf; /* Buffer for IPC_INFO*/ } semopts;
sem_num:将要处理的信号量的下标。 sem_op :要执行的操作类型; P:-1; V:1 sem_flg:操作标志:通常为SEM_UNDO或IPC_NOWAIT nsops:表明要操作的信号量的个数
void V(int semid,int index) //对标记符为semid的信号量集 中的第index个 //元素进行P操作(信号量操作要用到semop()函数) { struct sembuf sem; //此数据类型在sys/sem.h中定义 sem.sem_num = index;//对信号量集中的第index个元素进行P操作 sem.sem_op = 1; //表示V操作 sem.sem_flg = 0; //操作标记:0或IPC_NOWAIT等 semop(semid,&sem,1);//1:表示要操作1个信号量 }
注意事项
6) struct Person{char *name;int age}*p;
p->name = "zhangsan"; p->age = "22"; 此写法是错误的; 正确的写法是:
struct Person{char *name;int age}*p;
参数:th:线程号; thread_retrun: 用户定义的指针,用来存储被等待线程的返回值
作用:挂起当前线程直到由参数th指定的线程被终止为止。
示例:
pthread_create(&p1,NULL,subp1,NULL);//创建 计算线程p1 pthread_create(&p2,NULL,subp2,NULL);//创建 打印线程p2 pthread_join(p1,NULL);//主线程等待p1结束 pthread_join(p2,NULL);//主线程等待p2结束
返回
返回
实验一之线程实现缓冲区读写: 两个线程,共享公共变量a; 线程1负责计算(+1);线程2负责打印 思路: main()
{ (1) 创建信号量(集);
(2)初始化信号量(集); (3)创建两个线程subp1、subp2; * (线程subp1中进行计算;线程subp2中进行打印) (4)等待两个线程运行结束; (5)删除信号量(集); }
返回
Linux进程查看
ps命令 该命令可以确定有哪些进程正在运行和运行的状态、 进程是否结束、进程有没有僵死、哪些进程占用了 过多的资源等等
语法格式如下: ps [选项] 常用选项说明: -e 显示所有进程部分信息。 -f 显示某一进程详细信息。
一个简单的进程创建程序
系统调用semop():操作信号量
原型int semop(int semid,struct sembuf *sops,unsigned nsops); 返回值:成功返回0;失败返回1; struct sembuf//在sys/sem.h中有定义
{ ushort sem_num; short sem_op; short sem_flg; }
注意事项
1) 在Ubuntu中编译程序的时候,注意要将-lpthread 加到被编译的文件名之后,否则编译会出错; 2) semid和data应该定义为全局变量,否则创建的子 线程访 问不到; 3) 子线程执行的函数的返回值如果没有定义为void *,那么 在创建子线程的时候,要在参数前加上(void*); 4) rehhat linux:#include<sys/sem.h> Ubuntu:加入#include<linux/sem.h>不要包含头 文件sys/ipc.h 5)IPC_CREAT不要写错;不是IPC_CREATE
返回
信号量(集)的初始化以及删除:
系统调用semctl()
原型:int semctl(int semid,int semnum,int cmd[,union semun arg]); 返回值:如果成功,返回一个非负数;失败,则返回-1。 参数cmd中常使用的命令如下: SETVAL: 设置信号量集中的一个单独的信号量的值。
参数:thread:所创建的线程号。
attr:所创建的线程属性。 start_routine:即将运行的线程函数。 art:传递给线程函数的参数。 2)线程挂起: int pthread_join(pthread_t th, void **thread_retrun);
返回值:成功-返回0,失败-返回错误编号