리눅스 AIO 사용 문의

santa1000의 이미지

리눅스 AIO 사용 문의

OS : ubuntu 16.04 LTS
lib : boost(thread), librt(AIO)
AIO 참조 url : https://www.ibm.com/developerworks/library/l-async/index.html

안녕하세요 linux에서 AIO를 이용 파일 쓰기 프로그램을 작성하는데 문제가 있어 고수님들의 조언이 필요합니다.

AIO를 이용하여 단순히 텍스트 파일에 데이터를 쓰는 프로그램을 구현하려고 합니다.

2개의 Thread가 돌면서 A.txt, B.txt 파일을 쓰게 하려고 합니다.

문제는 각각의 Thread를 1개씩 돌리면 잘 작동이 되지만, 두 Thread를 동시에 돌리면

둘중 하나는 몇번정도 write를 수행하고 멈추고 나머지 Thread만 계속해서 write를 진행 합니다.

AIO 구현하면서 signal을 받아서 처리하며 signal 함수는 static으로 선언 되어야 하기에 1개의 객체로 부터 만들어진

여러개의 인스턴스때문에 영향을 미치는거 싶어 서로 간섭 안되도록 클래스도 별도로 만들어서 해봤지만 결과는 동일 했습니다.

소스 파일 같이 첨부합니다. (소스내 참조와 변수는 실제 사용하지 않는게 많이 있을 수 있습니다.)
총 3개의 파일 : main, samplethread.h,samplethread.cpp

######### main 파일 ############
 
#include "samplethread.h"
 
#define _GNU_SOURCE
 
#include <string>
#include <stdio.h>
 
 
#define DWORD_ unsigned int
 
#ifdef WIN32
#include <Windows.h>
#include <conio.h>
#endif
#include <vector>
#include <memory>
 
#include <boost/thread.hpp>
#include <boost/multi_array.hpp>
#include<fstream>
#include<iostream>
 
#ifndef WIN32
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <time.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/mman.h>
#include <pthread.h>
#include <sched.h>
#include <aio.h>
#include <signal.h>
#endif
 
 
int main(int argc, char* argv[])
{
 
    CSampleThread Cthread;
    Cthread.Init();
 
    CSampleThread Cthread2;
    Cthread.Init2();
 
 
//    int pid;
//    pid = fork();
 
//    if(pid ==0)
//    {
//        CSampleThread Cthread;
//        Cthread.Init();
//    }
//    else
//    {
//        CSampleThread2 Cthread2;
//        Cthread2.Init2();
//    }
 
 
    while(true)
        usleep(1000000);
 
};
 
 
########## samplethread.cpp 파일 #########
 
 
 
#include "samplethread.h"
 
 
void Aio_completion_handler( int signo, siginfo_t *info, void *context);
void Aio_completion_handler2( int signo, siginfo_t *info, void *context);
void Callback_aio_completion_handler(sigval_t sigval);
 
 
struct CSampleThread::Runner
 {
     CSampleThread* sampleThread;
     Runner(CSampleThread* r)
         : sampleThread(r)
     {
 
     }
 
     /**
     * operator() is the implementation of the device running logic.
     */
     //commit test
     void operator()()
     {
        sampleThread->Signal_aio_init();
     }
 };
 
struct CSampleThread::Runner2
 {
     CSampleThread* sampleThread2;
     Runner2(CSampleThread* r)
         : sampleThread2(r)
     {
 
     }
 
     /**
     * operator() is the implementation of the device running logic.
     */
     //commit test
     void operator()()
     {
        sampleThread2->Signal_aio_init2();
     }
 };
 
 
 
 
CSampleThread::~CSampleThread()
{
    //fclose(output);
}
 
 
void CSampleThread::Init()
{
    m_IORunner = std::shared_ptr<Runner>(new Runner(this));
    m_IOThread = std::shared_ptr<boost::thread>(new boost::thread(boost::ref(*m_IORunner)));
 
}
 
void CSampleThread::Init2()
{
    m_IORunner2 = std::shared_ptr<Runner2>(new Runner2(this));
    m_IOThread2 = std::shared_ptr<boost::thread>(new boost::thread(boost::ref(*m_IORunner2)));
}
 
 
 
void CSampleThread::Signal_aio_init()
{
    int fd;
    int temp = 1024*512;
    int ret = 0;
 
    char * buf[temp];
    //char * buf;
    //buf = new char[512*KB];
 
    bzero((char *)&my_aiocb, sizeof(struct aiocb));
    //memset(buf, 0, 1024);
    memset(buf, 0, temp);
 
    //file
    mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
    char * name = "//media/z87c/Data/AIO_test1.txt";
    fd = open(name, O_CREAT |O_APPEND | O_WRONLY | O_TRUNC | O_DIRECT , mode );
 
    /* Set up the signal handler */
    sigemptyset(&sig_act.sa_mask);
    sig_act.sa_flags = SA_SIGINFO;
    sig_act.sa_sigaction = Aio_completion_handler;
 
 
    /* Set up the AIO request */
    bzero( (char *)&my_aiocb, sizeof(struct aiocb) );
    my_aiocb.aio_fildes = fd;
    my_aiocb.aio_buf = buf;
    my_aiocb.aio_nbytes = temp;
    my_aiocb.aio_offset = 0;
 
    /* Link the AIO request with the Signal Handler */
    my_aiocb.aio_sigevent.sigev_notify = SIGEV_SIGNAL;
    my_aiocb.aio_sigevent.sigev_signo = SIGIO;
    my_aiocb.aio_sigevent.sigev_value.sival_ptr = &my_aiocb;
 
    /* Map the Signal to the Signal Handler */
    ret = sigaction( SIGIO, &sig_act, NULL );
 
    ret = aio_write( &my_aiocb );
}
 
 
void CSampleThread::Signal_aio_init2()
{
    int fd;
    int temp = 1024*256;
    int ret = 0;
 
    char * buf[temp];
 
    bzero((char *)&my_aiocb2, sizeof(struct aiocb));
    memset(buf, 0, temp);
 
    //file
    mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
    char * name = "//media/z87c/Data/AIO_test2.txt";
    fd = open(name, O_CREAT |O_APPEND | O_WRONLY | O_TRUNC | O_DIRECT , mode );
 
    /* Set up the signal handler */
    sigemptyset(&sig_act2.sa_mask);
    sig_act2.sa_flags = SA_SIGINFO;
    sig_act2.sa_sigaction = Aio_completion_handler2;
 
 
    /* Set up the AIO request */
    bzero( (char *)&my_aiocb2, sizeof(struct aiocb) );
    my_aiocb2.aio_fildes = fd;
    my_aiocb2.aio_buf = buf;
    my_aiocb2.aio_nbytes = temp;
    my_aiocb2.aio_offset = 0;
 
    /* Link the AIO request with the Signal Handler */
    my_aiocb2.aio_sigevent.sigev_notify = SIGEV_SIGNAL;
    my_aiocb2.aio_sigevent.sigev_signo = SIGIO;
    my_aiocb2.aio_sigevent.sigev_value.sival_ptr = &my_aiocb2;
 
    /* Map the Signal to the Signal Handler */
    ret = sigaction( SIGIO, &sig_act2, NULL );
 
    ret = aio_write( &my_aiocb2 );
}
 
 
//void CSampleThread::My_aio_write()
//{
//    ret = aio_write( &my_aiocb );
//}
 
 
void CSampleThread::Aio_completion_handler( int signo, siginfo_t *info, void *context )
{
    struct aiocb *req;
    int ret = 0;
 
    /* Ensure it's our signal */
    if (info->si_signo == SIGIO)
    {
 
        req = (struct aiocb *)info->si_value.sival_ptr;
 
        /* Did the request complete? */
        if (aio_error( req ) == 0)
        {
            //req->aio_buf = buf;
            /* Request completed successfully, get the return status */
            //ret = aio_return( req );
 
            //My_aio_write();
            ret = aio_write( req );
        }
    }
 
}
 
void CSampleThread::Aio_completion_handler2( int signo, siginfo_t *info, void *context )
{
    struct aiocb *req;
    int ret = 0;
 
    /* Ensure it's our signal */
    if (info->si_signo == SIGIO)
    {
        req = (struct aiocb *)info->si_value.sival_ptr;
 
        /* Did the request complete? */
        if (aio_error( req ) == 0)
        {
            //req->aio_buf = buf;
            /* Request completed successfully, get the return status */
            //ret = aio_return( req );
            //My_aio_write();
 
            ret = aio_write( req );
        }
    }
 
}
 
################## samplethread.h ####################
 
#ifndef SAMPLETHREAD_H
#define SAMPLETHREAD_H
 
#endif // SAMPLETHREAD_H
 
#define _GNU_SOURCE
 
#include <string>
#include <stdio.h>
 
 
#define DWORD_ unsigned int
 
#ifdef WIN32
#include <Windows.h>
#include <conio.h>
#endif
#include <vector>
#include <memory>
 
#include <boost/thread.hpp>
#include <boost/multi_array.hpp>
#include<fstream>
#include<iostream>
 
#ifndef WIN32
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <time.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/mman.h>
#include <pthread.h>
#include <sched.h>
#include <aio.h>
#include <signal.h>
#include<fstream>
#endif
 
 
class CSampleThread
{
 
public:
 
 
    /// DMA thread.
    std::shared_ptr<boost::thread> m_IOThread;
 
    /// DMA thread functor.
    struct Runner;
    std::shared_ptr<Runner> m_IORunner;
 
 
    /// DMA thread.
    std::shared_ptr<boost::thread> m_IOThread2;
 
    /// DMA thread functor.
    struct Runner2;
    std::shared_ptr<Runner2> m_IORunner2;
 
 
    static int temp;
    static char * test_buf;
    //const unsigned long long size = 8ULL * 1024ULL * 1024ULL;
 
    FILE * output;
    //fstream dataFile;
    clock_t t;
 
    bool B_Start[8];
    float time;
 
    unsigned long long WSpeed[8];
    unsigned long long second_keep = 0;
    unsigned long long dur = 0;
    unsigned long long start_dur = 0;
    unsigned long long end_dur = 0;
    unsigned long long single_buffer = 1;
    unsigned long long v2_single_buffer = 1;
 
    ~CSampleThread();
    static void Aio_completion_handler( int signo, siginfo_t *info, void *context );
    static void Aio_completion_handler2( int signo, siginfo_t *info, void *context );
    void Signal_aio_init();
    void Signal_aio_init2();
    void My_aio_write();
    void Init();
    void Init2();
 
 
    int hFile[8];
    int hFile__;
 
 
    std::string fname;
    std::string name;
    std::string d_name[8];
 
    int i_numBuffer = 8;
    int i_numThread = 0;
    int i_fileSize = 0;
    unsigned long long  n_fileSizeByte = 0;
    unsigned long long datasize = 0;
    unsigned long long secdatasize = 0;
    std::vector<char*> buffer;
 
    char* v_buffer;
    char* v2_buffer;
    void *addr = NULL;
 
 
    //void* v_buffer;
    char* c_buffer;
 
    long long m_count[8];
    long long total_count[8];
    float SLEEP = 1;
    unsigned long long result  = 0;
 
    //bool m_flag = false;
 
    int aio_flg = 0;
 
    char * buf;
    int retval= 0;
    ssize_t nbytes;
    //int mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
 
    struct sigaction sig_act;
    struct sigaction sig_act2;
    struct aiocb my_aiocb;
    struct aiocb my_aiocb2;
 
 
};

shint의 이미지

Async IO on Linux: select, poll, and epoll
https://jvns.ca/blog/2017/06/03/async-io-on-linux--select--poll--and-epoll/

multithread epoll aio select kqueue 검색 내용 첨부합니다. fork() 도 있네요.
사이트 글중에는 aio 의 멀티스레드? 사용이 리눅스 커널 2.6인가 이상이어야 한다는 이야기도 있네요.

aio 를 사용하는 프로그램
- libuv (라이브러리)
- nginx (아파치 웹서버)
- samba 삼바 (네트워크 드라이브)

도구를 사용하시려면. 삼바 사용하시면 될거 같네요.

//
멀티 스레드 / epoll 관련. 책 예제소스를 보셔도 될것 같습니다.
네이버 북 검색 결과도 함께 첨부해봅니다.

//
multi thread - 코드 프로젝트
https://www.codeproject.com/search.aspx?q=multi+thread&doctypeid=1%3b2%3b3%3b13%3b14

https://en.cppreference.com/w/cpp/thread/async
https://en.cppreference.com/w/cpp/thread/mutex

http://www.cplusplus.com/reference/thread/thread/

C++11 multithreading tutorial
https://solarianprogrammer.com/2011/12/16/cpp-11-thread-tutorial/

//--------------------------
//내용 추가 (윈도우 인 경우) - 여러 스레드에서 하나의 값을 동시에 접근하는 경우. 오류 방지 방법
//--------------------------
- 크리티컬 섹션으로 변수를 각각 잡아주는 방법
- 이벤트와 WaitForSingleObject() 등을 사용하는 방법
- 또는 운좋게 잘되면? if() 문을 사용하셔도 되기도 합니다. ㅇ_ㅇ;;

Critical Section(임계 영역) - CRITICAL_SECTION -- Non sum qualis ERAM
http://eram.tistory.com/entry/%ED%94%84%EB%A1%9C%EC%84%B8%EC%8A%A4-%EB%8F%99%EA%B8%B0%ED%99%94-CRITICALSECTION

HaeJuK Lab -- [SYSTEM] CRITICAL_SECTION 사용법 및 문제점
http://girtowin.tistory.com/107

critical_section 클래스
https://msdn.microsoft.com/ko-kr/library/dd492843.aspx?f=255&MSPPError=-2147217396

C++ 유저모드 동기화 (CRITICAL_SECTION)
https://m.blog.naver.com/PostView.nhn?blogId=gimjoonbum&logNo=220689235081&proxyReferer=https%3A%2F%2Fwww.google.co.kr%2F

Working with CRITICAL_SECTION
https://www.codeguru.com/cpp/w-p/system/threading/article.php/c5693/Working-with-CRITICALSECTION.htm

크리티컬 섹션 - 네이버 북
https://book.naver.com/search/search.nhn?sm=sta_hty.book&sug=&where=nexearch&query=%ED%81%AC%EB%A6%AC%ED%8B%B0%EC%BB%AC+%EC%84%B9%EC%85%98

//
여러 스레드에서.
각각에 변수를 접근하면. 오류가 발생하지 않을겁니다.

댓글 첨부 파일: 
첨부파일 크기
Package icon bookmarks_18. 9. 20..html_.zip23.99 KB

----------------------------------------------------------------------------
젊음'은 모든것을 가능하게 만든다.

매일 1억명이 사용하는 프로그램을 함께 만들어보고 싶습니다.
정규 근로 시간을 지키는. 야근 없는 회사와 거래합니다.

각 분야별. 좋은 책'이나 사이트' 블로그' 링크 소개 받습니다. shintx@naver.com

santa1000의 이미지

도움주셔서 감사합니다. 알려주신 자료 확인 해보겠습니다.

shint의 이미지

//
구름 IDE
https://www.goorm.io/

//
How to install Boost on Ubuntu - Boost 설치
https://stackoverflow.com/questions/12578499/how-to-install-boost-on-ubuntu

sudo apt-get install libboost-all-dev
sudo apt-get install aptitude
aptitude search boost

//
Boost - 컴파일 옵션
mkdir -p ${c.cpp.set.build.path} && ${c.cpp.set.compiler} $(find ${c.cpp.set.src.path} -name *.cpp -o -name *.c) -o ${c.cpp.set.build.path}/${c.cpp.set.main.name} ${c.cpp.set.build.options} -lm -lrt -lpthread -lboost_system -std=c++14 -std=c++0x -lboost_thread

-lm -lrt -lpthread -lboost_system -lboost_thread

//기타
-std=c++14
-std=c++0x
-pedantic
-lboost_system
-lboost_thread-mt
-lboost-thread-gcc-xx-1_nn

/usr/include/boost/system/error_code.hpp:222:?undefined?reference?to?`boost::system::generic_category()'
/usr/include/boost/thread/pthread/thread_data.hpp:144: undefined reference to `vtable for boost::detail::thread_data_base'
https://stackoverflow.com/questions/3584365/boost-thread-error-undefined-reference
https://stackoverflow.com/questions/13467072/c-boost-undefined-reference-to-boostsystemgeneric-category/13468280
https://stackoverflow.com/questions/13467072/c-boost-undefined-reference-to-boostsystemgeneric-category

https://ideone.com/uUdkJI
http://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html
https://stackoverflow.com/questions/36577094/array-of-size-0-at-the-end-of-struct
error : invalid use of 'struct aiocb' with a zero-size array in 'class CSampleThread' [-Wpedantic] struct aiocb my_aiocb;
http://jeremyko.blogspot.com/2012/10/linux-asynchronous-io.html
http://pubs.opengroup.org/onlinepubs/009604599/basedefs/aio.h.html
struct aiocb
https://en.cppreference.com/w/cpp/container/array
https://kldp.org/node/160178

//#define _GNU_SOURCE
 
#include <string>
#include <stdio.h>
 
 
#define DWORD_ unsigned int
 
#ifdef WIN32
#include <Windows.h>
#include <conio.h>
#endif
 
#include <vector>
#include <memory>
 
#include <boost/thread.hpp>
#include <boost/multi_array.hpp>
#include<fstream>
#include<iostream>
 
#ifndef WIN32
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <time.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/mman.h>
#include <pthread.h>
#include <sched.h>
#include <aio.h>
#include <signal.h>
#endif
 
 
//#pragma commenct (lib, "rt.lib")
 
//########## samplethread.cpp 파일 #########
 
 
 
using namespace std;
 
//void Aio_completion_handler( int signo, siginfo_t *info, void *context);
//void Aio_completion_handler2( int signo, siginfo_t *info, void *context);
void Callback_aio_completion_handler(sigval_t sigval);
 
 
 
 
 
 
 
class CSampleThread
{
 
public:
	CSampleThread();
    ~CSampleThread();
 
	struct aiocb my_aiocb;
	struct aiocb my_aiocb2;
 
    /// DMA thread.
    std::shared_ptr<boost::thread> m_IOThread;
 
    /// DMA thread functor.
    struct Runner;
    std::shared_ptr<Runner> m_IORunner;
 
 
    /// DMA thread.
    std::shared_ptr<boost::thread> m_IOThread2;
 
    /// DMA thread functor.
    struct Runner2;
    std::shared_ptr<Runner2> m_IORunner2;
 
 
//    static int temp;
    static char * test_buf;
    //const unsigned long long size = 8ULL * 1024ULL * 1024ULL;
 
    FILE * output;
    //fstream dataFile;
    clock_t t;
 
    bool B_Start[8];
    float time;
 
    unsigned long long WSpeed[8];
    unsigned long long second_keep;
    unsigned long long dur;
    unsigned long long start_dur;
    unsigned long long end_dur;
    unsigned long long single_buffer;
    unsigned long long v2_single_buffer;
 
    static void Aio_completion_handler( int signo, siginfo_t *info, void *context );
    static void Aio_completion_handler2( int signo, siginfo_t *info, void *context );
    void Signal_aio_init();
    void Signal_aio_init2();
    void My_aio_write();
    void Init();
    void Init2();
 
 
    int hFile[8];
    int hFile__;
 
 
    std::string fname;
    std::string name;
    std::string d_name[8];
 
    int i_numBuffer;
    int i_numThread;
    int i_fileSize;
    unsigned long long  n_fileSizeByte;
    unsigned long long datasize;
    unsigned long long secdatasize;
    std::vector<char*> buffer;
 
    char* v_buffer;
    char* v2_buffer;
    void *addr = NULL;
 
 
    //void* v_buffer;
    char* c_buffer;
 
    long long m_count[8];
    long long total_count[8];
    float SLEEP;
    unsigned long long result;
 
    //bool m_flag = false;
 
    int aio_flg;
 
    char * buf;
    int retval;
    ssize_t nbytes;
    //int mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
 
    struct sigaction sig_act;
    struct sigaction sig_act2;
 
 //main.cpp:143:18: error: invalid use of 'struct aiocb' with a zero-size array in 'class CSampleThread' [-Wpedantic]
//     struct aiocb my_aiocb;
 
};
 
 
 
CSampleThread::CSampleThread()
{
	cout << "CSampleThread()" << endl;
    second_keep = 0;
    dur = 0;
    start_dur = 0;
    end_dur = 0;
    single_buffer = 1;
    v2_single_buffer = 1;
 
    hFile__ = 0;
 
    i_numBuffer = 8;
    i_numThread = 0;
    i_fileSize = 0;
    n_fileSizeByte = 0;
    datasize = 0;
    secdatasize = 0;
 
    v_buffer = NULL;
    v2_buffer = NULL;
    addr = NULL;
 
 
    c_buffer = NULL;
 
    SLEEP = 1;
    result  = 0;
 
    aio_flg = 0;
 
    buf = NULL;
    retval= 0;
}
 
CSampleThread::~CSampleThread()
{
	cout << "~CSampleThread()" << endl;
    //fclose(output);
}
 
 
struct CSampleThread::Runner
 {
     CSampleThread* sampleThread;
     Runner(CSampleThread* r)
         : sampleThread(r)
     {
		cout << "CSampleThread::Runner" << endl;
     }
 
     /**
     * operator() is the implementation of the device running logic.
     */
     //commit test
     void operator()()
     {
		cout << "CSampleThread::Runner - operator()" << endl;
        sampleThread->Signal_aio_init();
     }
 };
 
struct CSampleThread::Runner2
 {
     CSampleThread* sampleThread2;
     Runner2(CSampleThread* r)
         : sampleThread2(r)
     {
		cout << "CSampleThread::Runner2" << endl;
     }
 
     /**
     * operator() is the implementation of the device running logic.
     */
     //commit test
     void operator()()
     {
		cout << "CSampleThread::Runner2 - operator()" << endl;
        sampleThread2->Signal_aio_init2();
     }
 };
 
 
 
 
void CSampleThread::Init()
{
	cout << "CSampleThread::Init() 1" << endl;
    m_IORunner = std::shared_ptr<Runner>(new Runner(this));
	cout << "CSampleThread::Init() 2" << endl;
    m_IOThread = std::shared_ptr<boost::thread>(new boost::thread(boost::ref(*m_IORunner)));
	cout << "CSampleThread::Init() 3" << endl;
 
}
 
void CSampleThread::Init2()
{
	cout << "CSampleThread::Init2() 1" << endl;
    m_IORunner2 = std::shared_ptr<Runner2>(new Runner2(this));
	cout << "CSampleThread::Init2() 2" << endl;
    m_IOThread2 = std::shared_ptr<boost::thread>(new boost::thread(boost::ref(*m_IORunner2)));
	cout << "CSampleThread::Init2() 3" << endl;
}
 
 
 
void CSampleThread::Signal_aio_init()
{
	cout << "CSampleThread::Signal_aio_init() 1" << endl;
    int fd;
//    const int temp = 1024*512;
    int ret;
 
    ret = 0;
 
    char * buf[1024*512];
    //char * buf;
    //buf = new char[512*KB];
 
    bzero((char *)&my_aiocb, sizeof(struct aiocb));
    //memset(buf, 0, 1024);
    memset(&buf[0], 0, 1024*512);
 
    //file
    mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
    char * name = (char*)"AIO_test1.txt";
    fd = open(name, O_CREAT |O_APPEND | O_WRONLY | O_TRUNC | O_DIRECT , mode );
 
    /* Set up the signal handler */
    sigemptyset(&sig_act.sa_mask);
    sig_act.sa_flags = SA_SIGINFO;
    sig_act.sa_sigaction = Aio_completion_handler;
 
 
    /* Set up the AIO request */
    bzero( (char *)&my_aiocb, sizeof(struct aiocb) );
    my_aiocb.aio_fildes = fd;
    my_aiocb.aio_buf = buf;
    my_aiocb.aio_nbytes = 1024*512;
    my_aiocb.aio_offset = 0;
 
    /* Link the AIO request with the Signal Handler */
    my_aiocb.aio_sigevent.sigev_notify = SIGEV_SIGNAL;
    my_aiocb.aio_sigevent.sigev_signo = SIGIO;
    my_aiocb.aio_sigevent.sigev_value.sival_ptr = &my_aiocb;
 
	cout << "CSampleThread::Signal_aio_init() 2" << endl;
    /* Map the Signal to the Signal Handler */
    ret = sigaction( SIGIO, &sig_act, NULL );
 
	cout << "CSampleThread::Signal_aio_init() 3" << endl;
    ret = aio_write( &my_aiocb );
	cout << "CSampleThread::Signal_aio_init() 4" << endl;
}
 
 
void CSampleThread::Signal_aio_init2()
{
	cout << "CSampleThread::Signal_aio_init2() 1" << endl;
    int fd;
//    const int temp = 1024*256;
    int ret;
 
    ret = 0;
 
    char * buf[1024*512];
 
    bzero((char *)&my_aiocb2, sizeof(struct aiocb));
    memset(buf, 0, 1024*512);
 
    //file
    mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
    char * name = (char*)"AIO_test2.txt";
    fd = open(name, O_CREAT |O_APPEND | O_WRONLY | O_TRUNC | O_DIRECT , mode );
 
    /* Set up the signal handler */
    sigemptyset(&sig_act2.sa_mask);
    sig_act2.sa_flags = SA_SIGINFO;
    sig_act2.sa_sigaction = Aio_completion_handler2;
 
 
    /* Set up the AIO request */
    bzero( (char *)&my_aiocb2, sizeof(struct aiocb) );
    my_aiocb2.aio_fildes = fd;
    my_aiocb2.aio_buf = buf;
    my_aiocb2.aio_nbytes = 1024*512;
    my_aiocb2.aio_offset = 0;
 
    /* Link the AIO request with the Signal Handler */
    my_aiocb2.aio_sigevent.sigev_notify = SIGEV_SIGNAL;
    my_aiocb2.aio_sigevent.sigev_signo = SIGIO;
    my_aiocb2.aio_sigevent.sigev_value.sival_ptr = &my_aiocb2;
 
	cout << "CSampleThread::Signal_aio_init2() 2" << endl;
    /* Map the Signal to the Signal Handler */
    ret = sigaction( SIGIO, &sig_act2, NULL );
 
	cout << "CSampleThread::Signal_aio_init2() 3" << endl;
    ret = aio_write( &my_aiocb2 );
	cout << "CSampleThread::Signal_aio_init2() 4" << endl;
}
 
 
//void CSampleThread::My_aio_write()
//{
//    ret = aio_write( &my_aiocb );
//}
 
 
void CSampleThread::Aio_completion_handler( int signo, siginfo_t *info, void *context )
{
    struct aiocb *req;
    int ret = 0;
 
	cout << "CSampleThread::Aio_completion_handler()" << endl;
    /* Ensure it's our signal */
    if (info->si_signo == SIGIO)
    {
		cout << "info->si_signo == SIGIO" << endl;
        req = (struct aiocb *)info->si_value.sival_ptr;
 
        /* Did the request complete? */
        if (aio_error( req ) == 0)
        {
			cout << "aio_error( req )" << endl;
            //req->aio_buf = buf;
            /* Request completed successfully, get the return status */
            //ret = aio_return( req );
 
            //My_aio_write();
            ret = aio_write( req );
			cout << "aio_write( req ) 2" << endl;
        }
    }
 
}
 
void CSampleThread::Aio_completion_handler2( int signo, siginfo_t *info, void *context )
{
    struct aiocb *req;
    int ret = 0;
 
	cout << "CSampleThread::Aio_completion_handler2()" << endl;
    /* Ensure it's our signal */
    if (info->si_signo == SIGIO)
    {
		cout << "info->si_signo == SIGIO x" << endl;
        req = (struct aiocb *)info->si_value.sival_ptr;
 
        /* Did the request complete? */
        if (aio_error( req ) == 0)
        {
			cout << "aio_error( req ) x" << endl;
            //req->aio_buf = buf;
            /* Request completed successfully, get the return status */
            //ret = aio_return( req );
            //My_aio_write();
 
            ret = aio_write( req );
			cout << "aio_write( req ) x" << endl;
        }
    }
 
}
 
//################## samplethread.h ####################
 
#ifndef SAMPLETHREAD_H
#define SAMPLETHREAD_H
 
#endif // SAMPLETHREAD_H
 
 
#include <string>
#include <stdio.h>
 
 
#define DWORD_ unsigned int
 
#ifdef WIN32
#include <Windows.h>
#include <conio.h>
#endif
#include <vector>
#include <memory>
 
#include <boost/thread.hpp>
#include <boost/multi_array.hpp>
#include<fstream>
#include<iostream>
 
#ifndef WIN32
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <time.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/mman.h>
#include <pthread.h>
#include <sched.h>
#include <aio.h>
#include <signal.h>
#include<fstream>
#endif
 
 
 
 
int main()
{
	cout << "test" << endl;
 
    CSampleThread Cthread;
    Cthread.Init();
 
    CSampleThread Cthread2;
    Cthread.Init2();
 
 
//    int pid;
//    pid = fork();
 
//    if(pid ==0)
//    {
//        CSampleThread Cthread;
//        Cthread.Init();
//    }
//    else
//    {
//        CSampleThread2 Cthread2;
//        Cthread2.Init2();
//    }
 
 
    while(true)
        usleep(100);
 
    return 0;
}
 
 
#if 0
 
 
root@goorm:/workspace/test4/bin# ./main
test
CSampleThread()
CSampleThread::Init() 1
CSampleThread::Runner
CSampleThread::Init() 2
CSampleThread::Init() 3
CSampleThread()
CSampleThread::Init2() 1
CSampleThread::Runner2
CSampleThread::Init2() 2
CSampleThread::Init2() 3
CSampleThread::Runner2 - operator()
CSampleThread::Runner - operator()CSampleThread::Signal_aio_init2() 1
 
CSampleThread::Signal_aio_init() 1
CSampleThread::Signal_aio_init() 2
CSampleThread::Signal_aio_init() 3
CSampleThread::Signal_aio_init2() 2
CSampleThread::Signal_aio_init2() 3
CSampleThread::Signal_aio_init() 4
CSampleThread::Signal_aio_init2() 4
CSampleThread::Aio_completion_handler2()
info->si_signo == SIGIO x
CSampleThread::Aio_completion_handler2()
info->si_signo == SIGIO x
123
asd
 
 
#endif
 

//
아래 처럼 하니. SIGIO 2 개가 출력 되네요.

    CSampleThread Cthread;
    Cthread.Init();
    Cthread.Init2();
 
//    CSampleThread Cthread2;
//    Cthread.Init2();
 
 
#if 0
 
root@goorm:/workspace/test4/bin# ./main
test
CSampleThread()
CSampleThread::Init() 1
CSampleThread::Runner
CSampleThread::Init() 2
CSampleThread::Init() 3
CSampleThread::Init2() 1
CSampleThread::Runner2
CSampleThread::Init2() 2
CSampleThread::Init2() 3
CSampleThread::Runner2 - operator()
CSampleThread::Signal_aio_init2() 1
CSampleThread::Signal_aio_init2() 2
CSampleThread::Signal_aio_init2() 3
CSampleThread::Signal_aio_init2() 4
CSampleThread::Aio_completion_handler2()
info->si_signo == SIGIO x
CSampleThread::Runner - operator()
CSampleThread::Signal_aio_init() 1
CSampleThread::Signal_aio_init() 2
CSampleThread::Signal_aio_init() 3
CSampleThread::Signal_aio_init() 4
CSampleThread::Aio_completion_handler()
info->si_signo == SIGIO
 
#endif

//
Mutex 를 사용하니. 기존 방법으로도. 2 가지 출력이 동작하네요.

#include <mutex>
std::mutex g_pages_mutex;
 
void CSampleThread::Signal_aio_init()
{
    std::lock_guard<std::mutex> guard(g_pages_mutex);
}
 
void CSampleThread::Signal_aio_init2()
{
    std::lock_guard<std::mutex> guard(g_pages_mutex);
}
 
int main()
{
    CSampleThread Cthread;
    Cthread.Init();
 
    CSampleThread Cthread2;
    Cthread.Init2();
    return 0;
}
 
 
#if 0
 
root@goorm:/workspace/test4/bin# ./main
test
CSampleThread()
CSampleThread::Init() 1
CSampleThread::Runner
CSampleThread::Init() 2
CSampleThread::Init() 3
CSampleThread()
CSampleThread::Init2() 1
CSampleThread::Runner2
CSampleThread::Init2() 2
CSampleThread::Init2() 3
CSampleThread::Runner2 - operator()
CSampleThread::Signal_aio_init2() 1
CSampleThread::Signal_aio_init2() 2
CSampleThread::Signal_aio_init2() 3
CSampleThread::Signal_aio_init2() 4
CSampleThread::Aio_completion_handler2()
info->si_signo == SIGIO x
CSampleThread::Runner - operator()
CSampleThread::Signal_aio_init() 1
CSampleThread::Signal_aio_init() 2
CSampleThread::Signal_aio_init() 3
CSampleThread::Signal_aio_init() 4
CSampleThread::Aio_completion_handler()
info->si_signo == SIGIO
 
#endif

----------------------------------------------------------------------------
젊음'은 모든것을 가능하게 만든다.

매일 1억명이 사용하는 프로그램을 함께 만들어보고 싶습니다.
정규 근로 시간을 지키는. 야근 없는 회사와 거래합니다.

각 분야별. 좋은 책'이나 사이트' 블로그' 링크 소개 받습니다. shintx@naver.com

santa1000의 이미지

이제야 확인을 했습니다. 자세한 답변 감사드려요 한번 해볼께요.

santa1000의 이미지

이제야 확인을 했습니다. 자세한 답변 감사드려요 한번 해볼께요.

세벌의 이미지

kldp에서 소스코드 넣는 방법
https://kldp.org/node/158191
참고하세요.

santa1000의 이미지

제가 코드를 무식하게 넣었군요..감사합니다

karkayan의 이미지

일단 스레드가 첫번째 aio_write 함수 호출하고 바로 종료합니다. 싱글 스레드 프로그램과 별반 차이가 없네요.

시그널은 스레드가 아닌 프로세스로 전달됩니다. 그리고 같은 번호의 시그널 여러개가 동시에 (시그널 핸들러가 호출되기 전에) 한 프로세스로 도착하는 경우, 리눅스에서는 하나만 처리됩니다.
지금은 파일별로 시그널이 생기는데, 실행중에 두 파일에 대한 시그널이 동시에 나오면, 하나는 무시되어 문제가 생기는 듯 합니다. 시그널 핸들러에서 aio 두개를 모두 확인하고 처리하면 될것 같습니다.

한가지 더 말하자면, aio_write는 signal handler에서 사용하기에 안전하지 않습니다. 자세한 내용은 signal-safety 를 검색해보세요.

santa1000의 이미지

그렇군요 그래서 인지 2개를 같이 돌려서 같은번호 시그널이 연속으로 와서 하나의 시그널은 무시가 된거 같아요.
그래서 인지 지정함수 signal handler1 signal handler2 를 등록 하고 돌려보면 어느순간 둘중 하나는 더 이상 시그널이 방생하지 않습니다. 그런데 특이한건 그 후부턴 signal handler로 2개 i/o 시그널이 순차적으로 들어옵니다.

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.