溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

Linux 系統(tǒng)函數(shù)open、close、read、writ

發(fā)布時(shí)間:2020-05-25 19:55:56 來源:網(wǎng)絡(luò) 閱讀:10888 作者:SherryX 欄目:系統(tǒng)運(yùn)維

系統(tǒng)調(diào)用

系統(tǒng)調(diào)用是操作系統(tǒng)提供給用戶的一組“特殊接口”。系統(tǒng)調(diào)用并非直接和程序員或系統(tǒng)管理員直接打交道,而是通過軟中斷的方式向內(nèi)核提交請(qǐng)求,從而獲取內(nèi)核函數(shù)的服務(wù)入口(系統(tǒng)調(diào)用表)。系統(tǒng)調(diào)用讓系統(tǒng)從用戶空間進(jìn)入內(nèi)核空間內(nèi)運(yùn)行,運(yùn)行后將結(jié)果返回給應(yīng)用程序(內(nèi)核態(tài)->用戶空間)。
Linux 系統(tǒng)函數(shù)open、close、read、writ
<br>

系統(tǒng)調(diào)用和系統(tǒng)API等區(qū)別

<br>
系統(tǒng)API
主要是通過C庫(kù)libc來實(shí)現(xiàn),程序員多采用這種方式與內(nèi)核交互,這些API通過系統(tǒng)調(diào)用來實(shí)現(xiàn)
<br>
系統(tǒng)命令
系統(tǒng)管理員采用系統(tǒng)命令與內(nèi)核交互,是一個(gè)可執(zhí)行文件,通過系統(tǒng)API及系統(tǒng)調(diào)用來實(shí)現(xiàn)
<br>
外殼程序
一系列系統(tǒng)命令和SHELL腳本共同組合成的程序。
<br>

函數(shù)庫(kù)調(diào)用 與 系統(tǒng)調(diào)用

Linux 系統(tǒng)函數(shù)open、close、read、writ
<br>

文件描述符

<br>
-每個(gè)進(jìn)程PCB結(jié)構(gòu)中有文件描述符指針,指向files_struct的文件描述符表,記錄每個(gè)進(jìn)程打開的文件列表
-系統(tǒng)內(nèi)核不允許應(yīng)用程序訪問進(jìn)程的文件描述符表,只返回這些結(jié)構(gòu)的索引即文件描述符ID(File Description)給應(yīng)用程序
-Linux系統(tǒng)中,應(yīng)用程序通過這些文件描述符來實(shí)現(xiàn)讓內(nèi)核對(duì)文件的訪問
-每個(gè)進(jìn)程能夠訪問的文件描述符是有限制的,通過#ulimit –n可以查看
<br>

特殊文件描述符

<br>標(biāo)準(zhǔn)輸入STDIN_FILENO
標(biāo)準(zhǔn)輸出STDOUT_FILENO
標(biāo)準(zhǔn)錯(cuò)誤STDERR_FILENO

<br>每個(gè)進(jìn)程被加載后,默認(rèn)打開0,1,2這三個(gè)文件描述符

<br>

open

<br>
-函數(shù)原型
int open(const char *path, int flags,mode_t mode);
-參數(shù)
path :文件的名稱,可以包含(絕對(duì)和相對(duì))路徑
flags:文件打開模式
mode: 用來規(guī)定對(duì)該文件的所有者,文件的用戶組及系統(tǒng)中其他用戶的訪問權(quán)限,則文件權(quán)限為:mode&(~umask)
-返回值
打開成功,返回文件描述符;
打開失敗,返回-1

<br>

打開方式

Linux 系統(tǒng)函數(shù)open、close、read、writ

訪問權(quán)限

Linux 系統(tǒng)函數(shù)open、close、read、writ
<br>
O_CREATE會(huì)產(chǎn)生特殊權(quán)限,需要設(shè)置訪問權(quán)限:
S_IRWXU等價(jià)于 S_IRUSR|S_IWUSR|S_IXUSR (文件所有者)
S_IRWXG 等價(jià)于 S_IRGRP|S_IWGRP|S_IXGRP (文件用戶組)
S_IRWXO 等價(jià)于 S_IROTH|S_IWOTH|S_IXOTH (文件其他用戶)
<br>

close

關(guān)閉文件close(將進(jìn)程中fd對(duì)應(yīng)的文件描述表結(jié)構(gòu)釋放):
函數(shù)原型:int close(int fd); //如果出現(xiàn)錯(cuò)誤,返回-1;調(diào)用成功返回0
<br>

read

-函數(shù)原型:
int read(int fd, void *buf, size_t nbytes);
-參數(shù)
fd :想要讀的文件的文件描述符
buf: 指向內(nèi)存塊的指針,從文件中讀取來的字節(jié)放到這個(gè)內(nèi)存塊中
nbytes: 從該文件復(fù)制到buf中的字節(jié)個(gè)數(shù)
-返回值
如果出現(xiàn)錯(cuò)誤,返回-1;
返回從該文件復(fù)制到規(guī)定的緩沖區(qū)中的字節(jié)數(shù)!
<br>

write

-函數(shù)原型:int write(int fd,void *buf,size_t nbytes);
-函數(shù)參數(shù):
fd :要寫入的文件的文件描述符
buf: 指向內(nèi)存塊的指針,從這個(gè)內(nèi)存塊中讀取數(shù)據(jù)寫入 到文件中
nbytes: 要寫入文件的字節(jié)個(gè)數(shù)
-返回值
如果出現(xiàn)錯(cuò)誤,返回-1
如果寫入成功,則返回寫入到文件中的字節(jié)個(gè)數(shù)
<br>
練習(xí):采用文件系統(tǒng)調(diào)用的方式,完成串口通訊配置文件的讀寫
<br>
配置文件serial.cfg如下:
Linux 系統(tǒng)函數(shù)open、close、read、writ
<br>
要求:1、程序運(yùn)行命令格式:
serialchat [-options];
[options]:
p-輸出打印serial.cfg各個(gè)配置項(xiàng)信息,格式:參數(shù)-----參數(shù)值;
s-進(jìn)行菜單(有保存和退出)讓用戶設(shè)置;
f-指定配配置項(xiàng)設(shè)置,輸出各選項(xiàng)置文件名,并輸出各配置項(xiàng)信息
其他選項(xiàng)提示該程序用法幫助。
2、不支持serialchat運(yùn)行兩次
3、如果無法找到配置文件,則提示運(yùn)行失敗,原因:配置文件無法找到
<br>
代碼如下:

#include   < stdio.h>
#include   < string.h>
#include   < sys/types.h>
#include   < sys/stat.h>
#include   < unistd.h>
#include    < fcntl.h>

int icount = 0;

//去空格 '\0'
void rm_space(char *pStr)
{
    char *pos = pStr;
    pos = strchr(pStr,' ');
    while(pos != NULL)
    {
        strcpy(pos,pos+1);
        pos = strchr(pos,' ');
    }
}

//去注釋 '#' '\n#'和中文,留下\n ... \r之間的數(shù)據(jù)
void rm_annotation(char *pStr)
{
    icount++;
    char *pos = pStr;
    char *end = NULL;
    if(icount == 1) //第一行有可能頂格
    {
        pos = strchr(pStr,'#');
    }
    else
    {
        pos = strstr(pStr,"\n#");
    }

    while(pos != NULL)
    {
        end = strchr(pos+1,'\n');
        strcpy(pos,end);
        pos = strstr(pStr,"\n#");
    }   

}

//輸出配置項(xiàng)信息
void printMsg(char *buf)
{
    char key[20] = " ";
    char value[20] = " ";
    char line[50] = " ";
    char *pos = buf;
    char *end = NULL;
    int flag = 0;

    printf("配置項(xiàng)信息如下:\n");

    pos = strchr(buf,'\n');
    end = strchr(pos,'=');

    while(end != NULL)
    {
        memset(key,0,sizeof(key));
        memset(value,0,sizeof(value));
        memcpy(key,pos+1,end - (pos + 1));

        pos = end;
        end = strchr(pos,'\r');
        if(end == NULL) //if the final data
        {
            flag = 1;
            break;
        }
        memcpy(value,pos+1,end - (pos + 1));

        sprintf(line,"%s-----%s",key,value);
        printf("%s\n",line);

        pos = end + 1;
        end = strchr(pos,'=');  
    }

    if(flag)    
    {
        end = strchr(pos,'\0');
        memcpy(value,pos+1,end - (pos + 1));
        sprintf(line,"%s-----%s",key,value);
        printf("%s\n",line);
    }
}

//修改配置文件 (傳入的buf是未經(jīng)處理的)
void updateFile(int fd,char *buf)
{
    char *pos = buf;
    char *end = NULL;
    char key[20] = "";
    char newvalue[20] = "";
    int lse;
    int count;

    printf("請(qǐng)輸入配置參數(shù): ");
    scanf("%s",key);
    printf("請(qǐng)輸入配置參數(shù)的值: ");
    scanf("%s",newvalue);
    strcat(key,"=");
    pos = strstr(buf,key);
    if(pos == NULL)
    {
        printf("輸入?yún)?shù)不存在!");
        return;
    }
    pos = pos + strlen(key);
    while(*pos == ' ')  //處理'='后面有空格的情況
    {
        pos = pos + 1;
    }
    end = strchr(pos,'\r');
    if(end == NULL) //if the final data
    {
        end = strchr(pos,'\0');
    }
    //修改文件
    lse = lseek(fd,pos-buf,SEEK_SET);
    write(fd,newvalue,end-pos); //注意新舊值的長(zhǎng)度
    printf("修改成功!\n");
}

/*--------------------主函數(shù)---------------------*/
int main(int argc,char *argv[])
{
    int fd;
    int readByte = 0;
    char buf[512] = "";
    char option[3] = "";
    char filename[20] = "";
    int  index;
    int s_flag = 0;
    int f_flag = 0;
    struct flock lock = {0};

    //判斷參數(shù)個(gè)數(shù)
    if(argc !=2 && argc != 3)
    {
        printf("輸入格式有誤!\n");
        return 1;
    }

    //打開配置文件
    strcpy(option,argv[1]);
    if(strcmp(option,"-f") == 0)    //打開指定文件
    {
        if(argc != 3)
        {
            printf("輸入格式有誤!\n");
            return 1;
        }
        f_flag = 1;
        strcpy(filename,argv[2]);
        fd = open(filename,O_RDWR,S_IRWXU|S_IRGRP);
    }
    else
    {
        fd = open("serial.cfg",O_RDWR,S_IRWXU|S_IRGRP);
    }

    if(fd == -1)
    {
        printf("運(yùn)行失敗,無法找到配置文件!\n");
        return 1;
    }

    //讀取配置文件
    readByte = read(fd,buf,512);
    if(readByte <= 0)
    {
        printf("讀文件失敗!\n");
        return 1;
    }

    //判斷是否已經(jīng)加鎖
    fcntl(fd,F_GETLK,&lock);
    if(lock.l_type != F_UNLCK)
    {
        printf("文件已經(jīng)被上鎖!執(zhí)行錯(cuò)誤\n");
        return 1;
    }
    //上鎖
    memset(&lock,0,sizeof(struct flock));
    lock.l_whence   = SEEK_SET;
    lock.l_start        = 0;
    lock.l_len      = sizeof(buf);
    lock.l_type     =F_WRLCK;
    if((fcntl(fd,F_SETLK,&lock)) == -1)
    {
        printf("設(shè)置寫鎖失??!\n");
        return 1;
    }

    //操作
    if(f_flag || strcmp(option,"-p") == 0)  //打印配置信息
    {
        rm_space(buf);
        rm_annotation(buf);
        printMsg(buf);
    }
    else if(strcmp(option,"-s") == 0)   //進(jìn)行菜單
    {
        while(!s_flag)
        {
            printf("1.修改配置項(xiàng)\n2.退出\n請(qǐng)輸入選擇: ");
            scanf("%d",&index);
            switch(index)
            {
                case 1:
                    updateFile(fd,buf);
                    break;
                case 2:
                    s_flag = 1;
                    break;
            }
        }

    }
    else
    {
        printf("serialchat用法:\n");
        printf("\t命令格式:serialchat [-options]\n ");
        printf("\t   [options]: p-輸出打印serial.cfg各個(gè)配置項(xiàng)信息\n ");
        printf("\t   [options]: s-進(jìn)行菜單\n ");
        printf("\t   [options]: f-指定配置文件\n ");
        printf("\t   [options]: 其他-查看幫助\n ");
    }

    //關(guān)閉文件
    close(fd);

    //釋放鎖
    lock.l_type     =F_UNLCK;
    fcntl(fd,F_SETLK,&lock);

    return 0;
}

運(yùn)行結(jié)果:
1、 serialchat –p
Linux 系統(tǒng)函數(shù)open、close、read、writ
2、 serialchat-s
Linux 系統(tǒng)函數(shù)open、close、read、writ

3、 serialchat-f
Linux 系統(tǒng)函數(shù)open、close、read、writ
4、 異常處理
Linux 系統(tǒng)函數(shù)open、close、read、writ
5、 上鎖
終端1:
Linux 系統(tǒng)函數(shù)open、close、read、writ
終端2:
Linux 系統(tǒng)函數(shù)open、close、read、writ

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI