[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[debian-users:26260] Re: auto-apt syscall wrapper



 こんにちは。島田です。

On Tue, 2 Jan 2001 19:59:33 +0900
TAKAMIYA Yasuhito <takamiya@xxxxxxxxxxxxxxxxxxxxxxxx> wrote:

> 「でぶあん」の うかいさんの auto-apt の記事をよんで思ったことです。

 読んでないので外していたらすみません。

> syscall を使うのが一般的、かつ簡単だと思います。

 syscall() システム・コールについては、libc6-dev を入れているのですが、
man には登録されていませんでした。rgrep してみたところ、unistd.h に次の
ように宣言がありましたが、何のために使うのか把握できていません。
 Google で検索しても、syscall() についての説明は見つかりませんでした。

#ifdef __USE_MISC
/* Invoke `system call' number SYSNO, passing it the remaining arguments.
   This is completely system-dependent, and not often useful.

   In Unix, `syscall' sets `errno' for all errors and most calls return -1
   for errors; in many systems you cannot pass arguments or get return
   values for all system calls (`pipe', `fork', and `getppid' typically
   among them).

   In Mach, all system calls take normal arguments and always return an
   error code (zero for success).  */
extern long int syscall __P ((long int __sysno, ...));

#endif  /* Use misc.  */

> 僕はチェックポインティングのライブラリを書いたりしているのですが、
> チェックポインティング時の状態を保存するために、
> たとえば open(2) を wrap して、
> 開いたファイルディスクリプタの状態だとか、
> lseek(2) を wrap してオフセットの状態を保存しておく必要性が出てくるわけです。
> (そして, failure の際にこれらの情報を復元する)

 もし、(この場合ファイル関係の操作ですが)1 アプリケーションのなかのみ
状態を保存するのであれば、クラスを 1 つ作ればすむのではないでしょうか。
 もし、システム全体にわたってと言うのであれば、だめでしょうけど。

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

class TFileOperator
{
private:
    std::string m_FileName;
    int         m_Fd;
    int         m_Flags;
    mode_t      m_Mode;

    // 必要があればいろいろな状態を保持するメンバ変数
    int         m_StateA;
    int         m_StateB;
protected:
    virtual void SetStateA(int State);
    virtual void SetStateB(int State);
    virtual int  GetStateA() const;
    virtual int  GetStateB() const;
public:
    TFileOperator();
    virtual ~TFileOperator();

    virtual void SetFileName(std::string FileName);
    virtual void SetFlags(int Flags);
    virtual void SetMode(int Mode);
    virtual int  Open();
    virtual int  Close();

    virtual ssize_t Read(void *Buf, size_t Count);
    virtual ssize_t Write(const void *Buf, size_t Count);
    virtual off_t   LSeek(int Fields, off_t Offset, int Whence);

    virtual int GetFileDiscribtor() const; // 何かのために

    // 何か、失敗するかもしれない操作。
    virtual void Operation();
};
==========================

===== FileOperator.cc =====
TFileOperator::TFileOperator()
{
    m_Fd = -1;
    m_Flags = 0; // 0 でも念のため
    m_Mode = 0;
}

TFileOperator::~TFileOperator()
{
    if(m_Fd >= 0) {
        Close();
    }
}


void TFileOperator::SetStateA(int State)
{
    m_StateA = State;
}

void TFileOperator::SetStateB(int State)
{
    m_StateB = State;
}

int  TFileOperator::GetStateA() const
{
    return m_StateA;
}

int  TFileOperator::GetStateB() const
{
    return m_StateB;
}


void TFileOperator::SetFileName(std::string FileName)
{
    m_FileName = FileName;
}

void TFileOperator::SetFlags(int Flags)
{
    m_Flags = Flags;
}

void TFileOperator::SetMode(int Mode)
{
    m_Mode = Mode;
}

int TFileOperator::Open()
{
    m_Fd = ::open(m_FileName.c_str(), m_Flags, m_Mode);

    return m_Fd;
}

int TFileOperator::Close()
{
    int ret = -1;

    if(m_Fd >= 0) {
        ret = ::close(m_Fd);
        if(ret != -1) {
            m_Fd = -1;
        }
    } else {
        ::errno = 0; // 本当は例外を送出するほうがよい
    }

    return ret;
}


ssize_t TFileOperator::Read(void *Buf, size_t Count)
{
    ssize_t ret = -1;

    if(m_Fd >= 0) {
        ret = ::read(m_Fd, Buf, Count);
    } else {
        ::errno = 0; // 本当は例外を送出するほうがよい
    }

    return ret;
}

ssize_t TFileOperator::Write(const void *Buf, size_t Count)
{
    ssize_t ret = -1;

    if(m_Fd >= 0) {
        ret = ::write(m_Fd, Buf, Count);
    } else {
        ::errno = 0; // 本当は例外を送出するほうがよい
    }

    return ret;
}

off_t TFileOperator::LSeek(int Fields, off_t Offset, int Whence)
{
    off_t ret = Offset - 1;

    if(m_Fd >= 0) {
        ret = ::lseek(Fields, Offset, Whence);
    } else {
        ::errno = 0; // 本当は例外を送出するほうがよい
    }

    return ret;
}


int TFileOperator::GetFileDiscribtor() const
{
    return m_Fd;
}

// 何か、失敗するかもしれない操作。
void TFileOperator::Operation()
{
    // ...
    
    // 現在の状態を保存
    SetStateA(stateA);
    SetStateB(stateB);
    int result = do_something();    // これが失敗するかもしれない
    if(result == 成功) {
        SetStateA(newStateA);
        SetStateB(newStateB);
    }
}


========================



----------------------------------------------------------------------
Mail: shimaden@xxxxxxxxx
Home Page: http://www.din.or.jp/~shimaden/
島田博幸
Hiroyuki Shimada
----------------------------------------------------------------------