美文网首页
系统编程-文件操作3

系统编程-文件操作3

作者: 帅碧 | 来源:发表于2016-12-01 16:24 被阅读0次
    • 作业:在文件任意位置处插入数据
    
    #include <stdio.h>
    #include <string.h>  //strerror()
    #include <errno.h>   //errno
    #include <unistd.h>  //write()  read() sleep()
    /*open()*/
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <fcntl.h>
    #define PER_IO_BYTES 4096
    int main(int argc,char *argv[])
    {
        int fd=-1;
        char caFile[32]={'\0'};//将原来文件保存再重命名
        strncpy(caFile,argv[1],sizeof(caFile));//将test.data里面的内容复制到caFile
    
        int ret=-1;
        strcat(caFile,".old");
        ret=rename(argv[1],caFile);//将原来的文件重命名
        if(-1==ret)
        {
            printf("rename error:%s\n",strerror(errno));//如果错误,打印错误信息
            return -1;
        }
        int fdNew=-1;
        fdNew=open(argv[1],O_WRONLY | O_CREAT,S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);//写打开,访问权限
        if(-1==fdNew)
        {
            printf("open error:%s\n",strerror(errno));
            return -1;
        }
        int fdOld=-1;
        fdOld=open(caFile,O_RDONLY);//读打开原来的文件
        if(-1==fdOld)
        {
            
            printf("open error:%s\n",strerror(errno));
            return -1;
        }
        off_t offset=0;//定义偏移量为5
        printf("please input position:");
        scanf("%ld",&offset);
        char caBuf[PER_IO_BYTES]={'\0'};//初始化
        int iLeft=offset;
        int iReaded=0;
        while(iLeft)//将指定位置前面的数据读出来
        {
            if(iLeft>=PER_IO_BYTES)
            {
                ret=read(fdOld,caBuf,PER_IO_BYTES);
            }
            else
            {
                ret=read(fdOld,caBuf,iLeft);
            }
            if(-1==ret)
            {
                printf("read error:%s\n",strerror(errno));
                break;
            }
            iLeft-=ret;
            ret=write(fdNew,caBuf,ret);
            if(-1==ret)
            {
                printf("write error:%s\n",strerror(errno));
                break;
                
            }
        }
        //在制定的位置插入该数据
        char *pData="$$$qqrhtewrywywruiepitrew$$$";
        ret=write(fdNew,pData,strlen(pData));
        if(-1==ret)
        {
            printf("write error:%s\n",strerror(errno));
            return;
            
        }
        offset=lseek(fdOld,0,SEEK_CUR);
        while(1)
        {
            ret=read(fdOld,caBuf,PER_IO_BYTES);
            if(-1==ret)
            {
                printf("read error:%s\n",strerror(errno));
                break;
                
            }
            else if(0==ret)
            {
                break;
            }
            ret=write(fdNew,caBuf,ret);
            if(-1==ret)
            {
                printf("write error:%s\n",strerror(errno));
                break;  
            }
        }
        close(fdNew);
        close(fdOld);
        ret=remove(caFile);
        if(-1==ret)
        {
            printf("remove error:%s\n",strerror(errno));
            return -1;
        }
        return 0;
    }
    
    //gcc lseek1.c
    //./a.out test.data
    //结果为:在第第四个位置插入数据:
    //1234$$$qqrhtewrywywruiepitrew$$$567890abcdefghijklmn
    
    

    ACCESS(测试)

    1. 测试文件是否存在
    #include<unistd.h>
    #include<stdio.h>//perror
    //mode:
    //    F_OK:测试文件是否存在
    //    R_OK:测试用户是否对文件具有可读权限
    //    W_OK:测试用户是否对文件具有可写权限
    //    X_OK:测试用户是否对文件具有可执行权限
    //测试用户对于指定的文件是否具有mode权限
    //如果有,则函数返回0
    //否则返回-1
    //int access(const char *pathname, int mode);
    int main(int argc,char *argv[])
    {
        int ret=-1;
        ret=access(argv[1],F_OK);//测试文件是否存在
        if(-1==ret)
        {
            perror("access");//如果错误,则会打印access:错误信息
            return -1;
        }
        else if(0==ret)
        {
            printf("file exist\n");
        }
        return 0;
    }
    //./a.out test.data
    
    
    1. 测试文件是否有可读可写权限
    #include<unistd.h>
    #include<stdio.h>//perror
    int main(int argc,char *argv[])
    {
        int ret=-1;
        ret=access(argv[1],R_OK | W_OK);//测试文件是否有可读可写的权限
        if(-1==ret)
        {
            perror("access");//如果错误,则会打印access:错误信息
            return -1;
        }
        else if(0==ret)
        {
            printf("user has those permissions\n");
        }
        return 0;
    }
    //./a.out test.data
    
    
    1. 测试文件是否有可执行权限
    #include<unistd.h>
    #include<stdio.h>//perror   
    int main(int argc,char *argv[])
    {
        int ret=-1;
        ret=access(argv[1],X_OK);//测试文件是否有可读可写的权限
        if(-1==ret)
        {
            perror("access");//如果错误,则会打印access:错误信息
            return -1;
        }
        else if(0==ret)
        {
            printf("user has those permissions\n");
        }
        return 0;
    }
    
    

    OPENDIR(打开目录)

    • 打开一个文件目录
    #include <stdio.h>
    #include <string.h>  //strerror()
    /*open()*/
    #include <sys/types.h>
    #include <dirent.h>
    int main(int argc,char *argv[])
    {
        //打开指定的目录,打开失败返回NULL,成功则返回一个指向目录的指针
        DIR *pDIR=opendir(argv[1]);
        if(NULL==pDIR)//打开失败
        {
            perror("opendir");
            return -1;
        }
        printf("opendir ok\n");
        closedir(pDIR);
    }
    
    //打开成功:opendir ok
    
    
    Paste_Image.png
    • 打开文件目录进行遍历目录里面的内容
    #include <stdio.h>
    #include <string.h>  //strerror()
    /*open()*/
    #include <sys/types.h>
    #include <dirent.h>
    int main(int argc,char *argv[])
    {
        //打开指定的目录,打开失败返回NULL,成功则返回一个指向目录的指针
        DIR *pDIR=opendir(argv[1]);
        if(NULL==pDIR)//打开失败
        {
            perror("opendir:");
            return -1;
        }
        printf("opendir ok\n");
        struct dirent *pDirent=NULL;
        pDirent=readdir(pDIR);//获得一个文件信息。遍历一个目录里的文件
        while(NULL !=pDirent)//继续读(可能有好多目录)
        {
            printf("%s ",pDirent->d_name);
            pDirent=readdir(pDIR);
        }
        printf("\n");
        closedir(pDIR);
    }
    //./a.out 1
    //./a.out ../上午
    //./a.out ../../11.30
    
    
    Paste_Image.png
    • 遍历目录内容,判断是普通文件还是目录文件还是其他类型
    #include <stdio.h>
    #include <string.h>
    /*stat()*/
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <unistd.h>
    /*opendir()*/
    #include <sys/types.h>
    #include <dirent.h>
    
    int main(int argc, char *argv[])
    {
        //打开指定的目录,打开失败返回NULL,并设置错误号
        //成功返回一个指向目录的指针
        DIR *pDir = opendir(argv[1]);
        if (NULL == pDir)
        {
            perror("opendir:");
            return -1;
        }
        printf("opendir ok\n");
        struct dirent *pDirent = NULL;
        struct stat fileStat;
        int ret = -1;
        pDirent = readdir(pDir);
        while (NULL != pDirent)
        {
            printf("%s ", pDirent->d_name);
            ret = stat(pDirent->d_name, &fileStat);
            if (0 == ret)
            {
                switch (fileStat.st_mode & S_IFMT)
                {
                case S_IFREG:
                    printf("这是一个普通的文件\n");
                    break;
                case S_IFDIR:
                    printf("这是一个目录的文件\n");
                    break;
                default:
                    printf("其他类型的文件\n");
                    break;
                }
            }
            else if (-1 == ret)
            {
                perror("stat");
                break;
            }
            pDirent = readdir(pDir);
        }
        printf("\n");
    
        //返回到目录的头部
        //rewinddir(pDirent);
        //创建一个目录
        //mkdir(pathname, mode);
        //删除一个目录
        //rmdir(pDrient);
    
        closedir(pDir);
    
        return 0;
    }
    //./a.out 1
    //./a.out ../上午
    
    
    Paste_Image.png
    • 求一个文件的普通文件的个数,目录文件的个数,其他类型文件的个数
    #include <stdio.h>
    #include <string.h>
    /*stat()*/
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <unistd.h>
    /*opendir()*/
    #include <sys/types.h>
    #include <dirent.h>
    int main(int argc,char *argv[])
    {
        DIR *pDir=opendir(argv[1]);
        if(NULL==pDir)
        {
            perror("opendir");
            return -1;
        }
        printf("opendir ok\n");
        struct dirent *pDirent=NULL;
        struct stat fileStat;
        int ret=-1;
        pDirent=readdir(pDir);
        int count=0,count1=0,count2=0;
        while(NULL!=pDirent)
        {
            printf("%s ",pDirent->d_name);
            ret=stat(pDirent->d_name,&fileStat);
            if(0==ret)
            {
                switch(fileStat.st_mode & S_IFMT)
                {
                    case S_IFREG:count++;break;
                    case S_IFDIR:count1++;break;
                    default:count2++;break;
                }
            }
            else if(-1==ret)
            {
                perror("stat");
                break;
            }
            pDirent=readdir(pDir);
        }
        printf("\n");
        printf("普通文件的个数为:%d\n",count);
        printf("目录文件的个数为:%d\n",count1);
        printf("其他类型文件的个数为:%d\n",count2);
        closedir(pDir);
    }
    //./a.out ../2
    
    
    
    Paste_Image.png

    进程

    1. 如何创建进程
    2. 如何使进程之间通信
    3. 如何销毁进程

    进程与程序的区别

    • 进程是动态的,程序是静态的
    • 一个程序可以运行多个进程,但是一个进程只一个程序服务

    进程控制块

    如何查看一个正在运行的进程

    • ps -A, kill -9 进程号

    如何查看进程的运行状态

    • top(表示CPU占了多少,占内存多少)

    如何创建进程

    • fork函数
    • 子进程会完全拷贝父进程,包括代码,包括资源
    • 父进程创建子进程,然后返回,子进程也返回,父进程返回子进程的pid,子进程返回0
    • 父进程先返则先父进程
    
    #include <unistd.h>   //fork()
    #include <stdio.h>
    #include <string.h>
    
    int main(void)
    {
        pid_t pid = -1;
        int iNum = 0;
        char caData[32] = {'\0'};
        //子进程创建后,和父进程属于两个相互独立的进程
        //父进程调用fork,这是一个系统调用,因此进入内核
        //内核根据父进程复制出一个子进程,父子进程的PCB信息相同
        //用户态代码和数据也完全相同。
        //因此,子进程现在的状态看起来和父进程一样,做完了初始化
        //刚调用了fork进入内核,还没有从内核返回。
        //现在有两个一模一样的进程看起来都调用了fork进入内核等待
        //从内核返回(实际上fork只调用了一次)。此外系统中还有其他
        //进程等待从内核返回。是父进程先返回还是子进程先返回,还是
        //父子进程都等待,其他进程先返回,这是不确定的。
        //取决于内核的调度算法
        pid = fork();
        //fork成功:将子进程的id返回给父进程的pid变量
        //          将0返回给子进程的pid变量
        //    失败:返回-1给父进程的pid变量,子进程不会被创建   
        //          并且错误号会被设置
        if (pid > 0)  //父进程
        {
            printf("this is parent process\n");
            strcpy(caData, "this is parent process\n");
            iNum = 3;
        }
        else if (0 == pid)  //子进程
        {
            printf("this is child process\n");
            strcpy(caData, "this is child process\n");
            iNum = 6;
        }
        else if (-1 == pid)  //创建进程失败
        {
            perror("fork");
            return -1;
        }
        int i = 0;
        for (; i < iNum; i++)
        {
            printf("%s", caData);
            sleep(1);   
        }
    
        printf("Hello World\n");
        return 0;
    }
    
    
    //父进程先结束,则是由祖宗进程对子进程进行善后
    
    
    Paste_Image.png
    #include <unistd.h>
    #include <stdio.h>
    #include <string.h>
    int main(void)
    {
        pid_t pid=-1;
        pid=fork();
        if(pid>0)//父进程
        {
            printf("this is parent progress\n");    
        }
        else if(pid==0)//子进程
        {
            printf("this is child progress\n"); 
        }
        else if(pid=-1)//创建进程失败
        {
            perror("fork");
            return -1;
        }
        while(1)
        {
        }
        printf("hello world\n");
        return 0;
    }
    //后台运行:./a.out &
    //同时创建两个进程:子进程与父进程
    
    
    Paste_Image.png Paste_Image.png
    • 父进程与子进程之间相互独立,父进程创建子进程,如果程序中不加while(1),则不能在后台显示,不加while(1)的结果如下:
    Paste_Image.png

    进程如何杀死

    • kill -9 +编号

    僵尸进程

    • 子进程结束后会释放一些资源,但是有些资源需要父进程进行释放,比如:进程号
    • 解决办法:僵尸进程,已死的进程,但仍然在后台,kill不行,因为是已死的进程,只能杀死父进程,最后由init祖宗进程进行
    1. 此为僵尸进程只有杀死父进程,则才能消灭子进程,否则之间kill子进程则仍然会在后台显示,虽然已经杀死,但是父进程没有进行清理,则仍然会存留(形成僵尸进程实例)
    #include <unistd.h>
    #include <stdio.h>
    #include <string.h>
    
    //一个进程结束时会关闭所有的文件描述符,
    //释放在用户空间分配的内存,
    //但它的PCB还保留着,
    //如果进程异常终止则保留着导致该进程终止的信号
    //如果正常终止则保留退出状态:在终端可以用“$?”来查看
    //父进程可以调用wait或waitpid获取这些信息,
    //然后彻底清楚掉这个进程
    
    //如果一个进程终止,但是其父进程尚未调用wait或者waitpid
    //对他进行清理,这时的进程状态称之为僵尸进程。
    
    //任何进程在刚终止的时候都是僵尸进程,
    //正常情况下僵尸进程会立刻被父进程清理。
    
    //僵尸进程的危害:
    //    系统允许存在的进程数是有上限的。
    //    若存在大量的僵尸进程,则可能创建新的进程由于没有
    //    进程号分配而失败
    
    
    //形成僵尸进程实例:
    int main(void)
    {
        pid_t pid=-1;
        pid=fork();
        if(pid>0)//父进程
        {
            printf("this is parent progress\n");
            while(1)
            {}
        }
        else if(pid==0)//子进程
        {
            printf("this is child progress\n");
        
        }
        else if(pid=-1)//创建进程失败
        {
            perror("fork");
            return -1;
        }
        while(1)
        {}
    }
    
    
    
    Paste_Image.png
    • 先删除子进程(结果如下,<defunct>,仍然存留在后台中)
    Paste_Image.png
    • 删除父进程,结果如下:已清理好()
    Paste_Image.png
    • 此为另一种解决方案(出力僵尸进程的方案)
    
    #include <unistd.h>
    #include <stdio.h>
    #include <string.h>
    #include<sys/wait.h>
    #include<sys/types.h>
    /*waitpid*/
    //僵尸进程的处理方式
    //1.将子进程的善后处理交给祖宗进程(父进程子在做自己的事,不方便对子进程清理)
    //  A-->B-->C:将B进程挂掉,那么C进程的清理工作由祖宗进程来清理
    //2.父进程自己调用相应的函数来对子进程做善后处理
    int main(void)
    {
        pid_t pid=-1;
        pid=fork();
        if(pid>0)//父进程
        {
            printf("this is parent progress\n");
            //阻塞等待子进程的结束
            //获得子进程的退出状态,并对子进程做清理工作
            wait(NULL);
            while(1)
            {}
        }
        else if(pid==0)//子进程
        {
            printf("this is first child progress\n");
            pid_t pid2=fork();
            if(pid2>0)
            {
                return 0;
            }
            else if(0==pid2)
            {
                int i=0;
                for(;i<3;i++)
                {
                    printf("this is second child process\n");
                }
                return 0;
            }
        }
        else if(pid=-1)//创建进程失败
        {
            perror("fork");
            return -1;
        }
    }
    
    
    • 创建一个父进程,写数据到文件里,子进程计算文件大小
    
    #include <unistd.h>
    #include <stdio.h>
    #include <string.h>
    #include <errno.h> 
    /*open()*/
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <fcntl.h>
    int main(int argc,char *argv[])
    {
        int fd=-1;
        pid_t pid=1;
        pid=fork(); 
        if(pid>0)
        {
            fd=open(argv[1],O_RDWR | O_CREAT | O_APPEND,S_IRUSR | S_IWUSR | S_IRGRP);
            if(-1==fd)
            {
                printf("open error:%s\n",strerror(errno));
                return -1;
            }   
            char *pData="hello world ";
            int ret=-1;
            while(1)
            {
                ret=write(fd,pData,strlen(pData));      
                if(-1==ret)
                {
                    perror("write");
                    return -1;
                }   
                sleep(1);   
            }
        }
        else if(0==pid)
        {   
            fd=open(argv[1],O_RDWR | O_CREAT | O_APPEND,S_IRUSR | S_IWUSR | S_IRGRP);
            
            off_t offset=-1;
            while(1)
            {
                offset=lseek(fd,0,SEEK_END);
                if(-1==offset)
                {
                    perror("lseek");
                    return -1;
                }
                printf("file size:%ld\n",offset);
                sleep(1);
            }
        }
        else if(-1==pid)
        {
            perror("fork");
            return -1;
        }   
        return 0;
    }
    
    

    //运行结果如下

    Paste_Image.png

    相关文章

      网友评论

          本文标题:系统编程-文件操作3

          本文链接:https://www.haomeiwen.com/subject/penxmttx.html