2015年7月21日星期二

Linux系统生成,进(线)程同步与通信,并发程序的誊抄,文件目录操作


0 Linux系统生成

步骤:
(1)安装Linux系统Ubuntu10.12
(2)使用ctrl+alt+T打开终端
(3)设置root用户及root用户密码:使用的命令如图所示

(4)进入root用户
(5)把源码包解压到 /usr/src/linux-3.6.3

(6)编译内核:使用make命令
(7)安装编译好的内核
(8)查看内核版本

1 实验一LINUX系统用户界面 实验二进(线)程同步与通信

1.1 实验目的

       1、掌握Linux系统用户界面中键盘命令的使用。
       2、学会一种Linux下的编程环境。
       3、掌握Linux下进(线)程的概念。
       4、了解Linux进程同步与通信的主要机制,并通过信号灯操作实现进程间的同步与互斥。

1.2 预备知识

1.2.1 Linux下的信号灯及其P、V操作
1. 1 PV操作定义
P操作
V操作
   void P(int semid,int index)
  {    struct sembuf sem;     
        sem.sem_num = index;
        sem.sem_op = -1;   
        sem.sem_flg = 0;      //:操作标记:0IPC_NOWAIT  
        semop(semid,&sem,1);          //1:表示执行命令的个数
        return;
}
   void V(int semid,int index)
  {    struct sembuf sem;     
        sem.sem_num = index;
        sem.sem_op =  1;
        sem.sem_flg = 0;     
       semop(semid,&sem,1);    
       return;
}



1.2.2 线程
1. 2 线程相关函数
线程创建
pthread_create(pthread_t  *thread, pthread_attr_t         *attr,
       void *(*start_routine)(void *),void *arg);
线程挂起
pthread_join(pthread_t th, void **thread_retrun);

1.2.3 共享内存
使用共享内存是运行在同一计算机上的进程进行进程间通信的最快的方法,shmget与shmat 系统调用。

1.2.4 进程控制
   fork与execv系统调用

1.2.5 编译、编辑、调试
1. 3 编译、编辑、调试
编译
cc –o  test  -g test.c –lpthread  
cc –o sub1 sub1.c
编辑
vi
调试
gdb

1.3 实验内容

实验一的程序要求:
    两个线程,共享公共变量a
    线程1负责计算(+1)
    线程2负责打印
实现:
       1、线程的同步与互斥
       2、进程的同步与互斥
       3、子进程的创建
1.4 运行结果

1. 1 运行结果

1.5 源代码
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <sys/types.h>
#include <linux/sem.h>
#define LOOPS 10
void P(int semid,int index);
void V(int semid,int index);
int semid;int a=0;
pthread_t p1,p2;
void *subp1();void *subp2();
void P(int semid,int index)
 {         
           struct sembuf sem;     
        sem.sem_num = index;
        sem.sem_op = -1;    
        sem.sem_flg = 0;       //:操作标记:0IPC_NOWAIT  
        semop(semid,&sem,1);               //1:表示执行命令的个数    
        return;
}
void V(int semid,int index)
{        
           struct sembuf sem;     
        sem.sem_num = index;
        sem.sem_op =  1;
        sem.sem_flg = 0;      
              semop(semid,&sem,1);         
              return;
}
void *subp1()
{        
           int i,j;         
           for (i=0;  i< LOOPS;i++)
           {                   
                     P(semid,0);                    
                     printf("subp1:a=%d\n",a); 
                     V(semid,1);         
           }        
           return;
}
void *subp2()
{        
           int i,j;         
           for (i=0;i<LOOPS;i++)
           {                   
                    P(semid,1);                    
                     a+=1;                    
                     V(semid,0);         
           }
           return;
}
main()
{        
           union semun  semopts;      
           int res;
           semid =semget(11,2,IPC_CREAT|0666);
           semopts.val = 0;
           res=semctl(semid,0,SETVAL,semopts);
           semopts.val = 1;
           res=semctl(semid,1,SETVAL,semopts);           
           pthread_create(&p1,NULL,subp1,NULL);      
           pthread_create(&p2,NULL,subp2,NULL);      
           pthread_join(p1,NULL);       
           pthread_join(p2,NULL);       
           semctl(semid,0,IPC_RMID,0);
}

2在linux下编程实现P98  4-11


2.1 实验目的
了解并发程序的执行过程和实现原理

2.2 预备知识

2.2.1 并发程序的誊抄


2. 1  誊抄过程
get程序:负责从输入序列f中读取字符并送到缓冲区s中;
copy程序:把缓冲区s中的数据复制到缓冲区t中去;
put程序:从缓冲区t中取出数据打印。

2.2.2 誊抄的实现

2. 2 誊抄的实现

在相应的圆圈对应的进程中,通过修改箭头上对应序号的信号灯控制进程的运行,设有4个信号灯分别为0、1、2、3
在进程中对信号灯的控制可简写为:
get()
{
           p(0);
           get操作;
           v(2);
}
copy()
{
           p(1);
           p(2);
           copy操作;
           v(0);
           v(3);
}
put()
{
           p(3);
           put操作;
           v(1);
}
通过设置信号灯0的初值和利用copy对信号灯0v操作,使得当信号灯0的资源个数>0时,可以进行get操作
通过设置信号灯12的初值和利用put对信号灯1v操作、利用get对信号灯2v操作,使得当信号灯1和信号灯2的资源个数均>0时,可以进行copy操作
通过设置信号灯3的初值和利用copy对信号灯3v操作,使得当信号灯3的资源个数>0时,可以进行put操作

2.3 实验内容

1、实现: main、get、copy、put 4个函数
2、将这四个函数编译链接(使用makefile)
2.4 运行结果

2. 3 运行结果
使用./main打开程序

2.5 源代码
main.c
#include<stdio.h>
#include<stdlib.h>
#include<linux/shm.h>
#include<sys/types.h>
#include<linux/sem.h>
#define LOOPS 10
#define IPCKEY (key_t)0x11
#define SHMKEY1 (key_t)0x222
#define SHMKEY2 (key_t)0x333
void P(int semid,int index);
void V(int semid,int index);
int semid;

void V(int semid,int index)
{
    struct sembuf sem;
    sem.sem_num = index;/*信号灯数组灯的一个索引,指明哪个信号灯*/
    sem.sem_op = 1;/*加到当前信号灯的数值*/
    sem.sem_flg = 0;
    semop(semid,&sem,1);
    return;
}
void P(int semid,int index)
{
    struct sembuf sem;
    sem.sem_num = index;
    sem.sem_op = -1;
    sem.sem_flg = 0;
    semop(semid,&sem,1);
    return;
}

int main(void)
{
    union semun semopts;
    int res,i;
    struct shmid_ds *buf;
    int cmd;
    int shmid1,shmid2;
    char *s,*t,ss[]="";
    pid_t p1,p2,p3;
   
   
    semid = semget(IPCKEY,4,IPC_CREAT|0666);  
    semopts.val = 1;
    res = semctl(semid,0,SETVAL,semopts);   
    semopts.val = 1;
    res = semctl(semid,1,SETVAL,semopts); 
    semopts.val = 0;
    res = semctl(semid,2,SETVAL,semopts);   
    semopts.val = 0;
    res = semctl(semid,3,SETVAL,semopts); 
    shmid1 = shmget(SHMKEY1,sizeof(char),IPC_CREAT|0666);  
    s=(char *)shmat(shmid1,NULL,SHM_R|SHM_W);
    shmid2 = shmget(SHMKEY2,sizeof(char),IPC_CREAT|0666);
    t=(char *)shmat(shmid2,NULL,SHM_R|SHM_W);
   
 
   
    if((p1=fork()) == 0){
        execv("./get",NULL);
        }
     else
     {
         if((p2=fork()) == 0){
             execv("./copy",NULL);
              }
          else
          {
              if((p3=fork())==0){
                 execv("./put",NULL);
                 }
           }
      }
      p1=wait(&p1);
      p2=wait(&p2);
      p3=wait(&p3);
      /*for(i=0;i<3;i++)
      {
          while(-1!=wait())
              ;
      }*/
      if(semctl(semid,0,IPC_RMID,0)<0)
      printf("error");
      shmctl(shmid1,IPC_RMID,0);
      shmctl(shmid2,IPC_RMID,0);
      return 0;
}

get.c
#include<stdio.h>
#include<stdlib.h>
#include<sys/types.h>
#include<linux/sem.h>
#include<linux/shm.h>
#define LOOPS 10
#define IPCKEY (key_t)0x11
#define SHMKEY1 (key_t)0x222
#define SHMKEY2 (key_t)0x333
void P(int semid,int index);
void V(int semid,int index);
int semid;

void V(int semid,int index)
{
    struct sembuf sem;
    sem.sem_num = index;/*信号灯数组灯的一个索引,指明哪个信号灯*/
    sem.sem_op = 1;/*加到当前信号灯的数值*/
    sem.sem_flg = 0;
    semop(semid,&sem,1);
    return;
}
void P(int semid,int index)
{
    struct sembuf sem;
    sem.sem_num = index;
    sem.sem_op = -1;
    sem.sem_flg = 0;
    semop(semid,&sem,1);
    return;
}
int main(void)
{
   
    int i=0;
    int shmid1;
    char *s,*t,str[]="linux!";/*str为输入的字符,实现一个一个字符的输入,输出,st指针当单个字符使用,即s[0],t[0]*/
   
    semid = semget(IPCKEY,4,IPC_CREAT|0666);
    shmid1 = shmget(SHMKEY1,sizeof(char),IPC_CREAT|0666);
    s=(char *)shmat(shmid1,NULL,SHM_R|SHM_W);/* 绑定到共享内存块 */
   
    do
    {
        P(semid,0);     
        s[0]=str[i];
        printf("get\n");
        i++;      
        V(semid,2);
       
     }while(s[0]!='\0');
}     


copy.c
#include<stdio.h>
#include<stdlib.h>
#include<sys/types.h>
#include<linux/sem.h>
#include<linux/shm.h>
#define LOOPS 10
#define IPCKEY (key_t)0x11
#define SHMKEY1 (key_t)0x222
#define SHMKEY2 (key_t)0x333
void P(int semid,int index);
void V(int semid,int index);
int semid;

void V(int semid,int index)
{
    struct sembuf sem;
    sem.sem_num = index;/*信号灯数组灯的一个索引,指明哪个信号灯*/
    sem.sem_op = 1;/*加到当前信号灯的数值*/
    sem.sem_flg = 0;
    semop(semid,&sem,1);
    return;
}
void P(int semid,int index)
{
    struct sembuf sem;
    sem.sem_num = index;
    sem.sem_op = -1;
    sem.sem_flg = 0;
    semop(semid,&sem,1);
    return;
}
int main(void)
{
   
    int j=0;
    int shmid1,shmid2;
    char *s,*t;
 
    semid = semget(IPCKEY,4,IPC_CREAT|0666);
    shmid1 = shmget(SHMKEY1,sizeof(char),IPC_CREAT|0666);
    s=(char *)shmat(shmid1,NULL,SHM_R|SHM_W);/* 绑定到共享内存块 */
    shmid2 = shmget(SHMKEY2,sizeof(char),IPC_CREAT|0666);
    t=(char *)shmat(shmid2,NULL,SHM_R|SHM_W);
    do
    {
    
        P(semid,1);
        P(semid,2);
        strcpy(t,s);
        printf("copy\n");
        V(semid,0);
        V(semid,3);
      
     }while(t[0]!='\0');
    
}


put.c
#include<stdio.h>
#include<stdlib.h>
#include<sys/types.h>
#include<linux/sem.h>
#include<linux/shm.h>
#define LOOPS 10
#define IPCKEY (key_t)0x11
#define SHMKEY1 (key_t)0x222
#define SHMKEY2 (key_t)0x333
void P(int semid,int index);
void V(int semid,int index);
int semid;


void V(int semid,int index)
{
    struct sembuf sem;
    sem.sem_num = index;/*信号灯数组灯的一个索引,指明哪个信号灯*/
    sem.sem_op = 1;/*加到当前信号灯的数值*/
    sem.sem_flg = 0;
    semop(semid,&sem,1);
    return;
}
void P(int semid,int index)
{
    struct sembuf sem;
    sem.sem_num = index;
    sem.sem_op = -1;
    sem.sem_flg = 0;
    semop(semid,&sem,1);
    return;
}
int main(void)
{
   
    int k=0;
    int shmid1,shmid2;
    char *s,*t;

    semid = semget(IPCKEY,4,IPC_CREAT|0666);
    shmid2 = shmget(SHMKEY2,sizeof(char),IPC_CREAT|0666);
    t=(char *)shmat(shmid2,NULL,SHM_R|SHM_W);/* 绑定到共享内存块 */
    do
    {
        /*if(t[0]=='\0')break;*/
        P(semid,3);
        if(t[0]!='\0')printf("put---->%c\n",*t);
        else printf("put---->\\0\n");
        V(semid,1);
      
     }while(t[0]!='\0');
    
 }
             
makefile
all:get copy put main
           echo "complete"
get:get.o
           gcc -o get get.o
copy:copy.o
           gcc -o copy copy.o
put:put.o
           gcc -o put put.o
main:main.o
           gcc -o main main.o
get.o:get.c
           gcc -c get.c
copy.o:copy.c
           gcc -c copy.c
put.o:put.c
           gcc -c put.c
main.o:main.c
           gcc -c main.c

3 实验三  Linux文件目录操作


3.1 实验目的、实验要求

3.1.1实验目的
了解并掌握Linux文件目录结构。

3.1.2 实验要求
了解Linux文件系统与目录操作:
(1) Linux文件系统 :文件属性;
(2)Linux目录结构:目录文件;
(3)目录相关函数接口;

3.2 实验内容
1、熟悉Linux文件系统的使用;
2、了解Linux文件系统目录结构;
3、编程实现目录查询命令;
•     功能类似ls -lR;
•     查询指定目录下的文件及子目录信息;
    显示文件的类型、大小、时间等信息;
•     递归显示子目录中的文件信息;

3.3 预备知识

3.3.1 Linux文件属性接口

3. 1 文件属性接口
函数
功能
int fstat(int fildes,struct stat *buf);
返回文件描述符相关的文件的状态信息
int lstat(const char *path, struct stat *buf);
如读取到了符号连接,读取符号连接本身的状态信息
int stat(const char *path, struct stat *buf);
如读取到了符号连接,读取的是符号连接指向文件的信息

stat结构体几乎保存了所有的文件状态信息:
本程序中主要用到st_mode 文件的权限信息和类型信息,检查类型时使用S_ISDIR(); 宏,检查是否是目录

3.3.2 Linux目录结构接口
3. 2 目录结构接口
函数
功能
DIR *opendir(const char *name);

通过路径打开一个目录,返回一个DIR结构体指针(目录流),失败返回NULL
struct dirent *readdir(DIR *)

读取目录中的下一个目录项,没有目录项可以读取时,返回为NULL
int chdir(const char *path);

改变目录,与用户通过cd命令改变目录一样,程序也可以通过chdir来改变目录,这样使得 fopen(),opendir(),这里需要路径的系统调用,可以使用相对于当前目录的相对路径打开文件(目录)
int closedir(DIR*)
关闭目录流

在本程序中,用到结构dirent中的char   d_name[256]; (文件名)项

3.4 运行结果

3. 1 运行结果

3.5 源代码
#include <unistd.h>
#include <sys/stat.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <dirent.h>

void printdir(char *dir, int depth){
    DIR *dp;
    struct dirent *entry;
    struct stat statbuf;
  
    if  (((dp = opendir(dir)))== NULL){     // opendir
        printf("Open Dir Failed!\n");
        return ;
    }
    chdir(dir);   //chdir

while( (entry=readdir(dp))!=NULL){   //readdir
           lstat(entry->d_name,&statbuf);
           if(S_ISDIR(statbuf.st_mode)){
            if(strcmp(entry->d_name,"..")==0||strcmp(entry->d_name,".")==0)
                 continue;
            printf("DIR DEPTH:          %d    ",depth);
           printf("DIR NAME:    %s\n",entry->d_name);
            printdir(entry->d_name,depth+1);
        }  
            else
           {
            printf("FILE DEPTH:         %d    ",depth);
           printf("FILE NAME:  %s\n",entry->d_name);
                     }    }
    chdir("..");//chdir
    closedir(dp); //closedir
}

int main(void){
    char a[50];
           printf("Input Dir Name!\n");
           scanf("%s",a);
           printdir(a,0);
           return 0;
}



没有评论:

发表评论