timer_create是否为处理程序创建新线程

时间:2017-03-14 04:52:14

标签: c linux

timer_settime()每秒构建一次计时器。信号处理程序是traffic_measurement_handlertraffic_measurement_handler是否在新线程中运行?当处理程序运行时如何让callback停止?

#define CLOCKID CLOCK_REALTIME
#define SIG SIGUSR1
timer_t timerid;

int main(void)
{
    ..

    build_timer();
    pcap_loop(pcap_handle, -1, callback, NULL);
}

void callback() // callback of Libpcap API: pcap_loop()
{
    detect_network_traffic(); // stop when timer expires, and then continue                 
                              // to run when traffic_measurement_handler has finished.
}

// timer handler runs every second to update database
void traffic_measurement_handler() 
{
    .. // This block will fetch global variables, so I want to
       // let callback stop when this handler is running.


    // rebuild the timer
    build_timer();

}

// set timer
void build_timer()
{
    sa.sa_flags = SA_SIGINFO;
    sa.sa_sigaction = traffic_measurement_handler;
    sigemptyset(&sa.sa_mask);
    sigaction(SIG, &sa, NULL);

    sev.sigev_notify = SIGEV_SIGNAL;
    sev.sigev_signo = SIG;
    sev.sigev_value.sival_ptr = &timerid;
    timer_create(CLOCKID, &sev, &timerid);

    its.it_value.tv_sec = 1;
    its.it_value.tv_nsec = 0;
    its.it_interval.tv_sec = its.it_value.tv_sec;
    its.it_interval.tv_nsec = its.it_value.tv_nsec;

    timer_settime(timerid, 0, &its, NULL);
}

信号处理程序在只存在一个线程的过程中是否安全?

已添加:第二版本  这是对的吗?

pthread_t thread_global;

int main(void)
{
    // register SIGUSR1 handler
    sa.sa_flags = SA_SIGINFO;
    sa.sa_sigaction = traffic_measurement_handler;
    sigemptyset(&sa.sa_mask);
    sigaction(SIG, &sa, NULL);

    pthread_create(&thread1, NULL, processing_thread, (void *) thread_id1);
    pthread_create(&thread2, NULL, timer_thread, (void *) thread_id2);
    pthread_join(thread1, NULL);
    pthread_join(thread2, NULL);    
}

void *processing_thread(void *thread_id)
{
    pcap_loop(pcap_handle, -1, callback, NULL);
}

void callback() // callback of Libpcap API: pcap_loop()
{
    thread_global = pthread_self();
    detect_network_traffic(); // stop when SIGUSR1 is caught, and then continue                 
                              // to run when traffic_measurement_handler has finished.
}

//update database every second when SIGUSR1 is caught
void traffic_measurement_handler()
{
    ..
}

//This thread is used to notify updating database every second.
void *timer_thread(void *thread_id)
{
    for (; ;) {
        sleep(1);
        pthread_kill(thread_global, SIGUSR1);
    }
}

2 个答案:

答案 0 :(得分:1)

要将计时器处理程序作为线程模式运行,您必须修改timer_create的值 请阅读 SIGEV_NONE Don't asynchronously notify when the timer expires. Progress of the timer can be monitored using timer_gettime(2). SIGEV_SIGNAL Upon timer expiration, generate the signal sigev_signo for the process. See sigevent(7) for general details. The si_code field of the siginfo_t structure will be set to SI_TIMER. At any point in time, at most one signal is queued to the process for a given timer; see timer_getoverrun(2) for more details. SIGEV_THREAD Upon timer expiration, invoke sigev_notify_function as if it were the start function of a new thread. See sigevent(7) for details. SIGEV_THREAD_ID (Linux-specific) As for SIGEV_SIGNAL, but the signal is targeted at the thread whose ID is given in sigev_notify_thread_id, which must be a thread in the same process as the caller. The sigev_notify_thread_id field specifies a kernel thread ID, that is, the value returned by clone(2) or gettid(2). This flag is intended only for use by threading libraries. Specifying sevp as NULL is equivalent to specifying a pointer to a sigevent structure in which sigev_notify is SIGEV_SIGNAL, sigev_signo is SIGALRM, and sigev_value.sival_int is the timer ID.

手册页中的以下引用
  

sevp.sigev_notify字段可以包含以下值:

timer_settime

另请查看callback enter image description here

的手册页

此处pcap_loop将充当不同的主题,因为protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.graph_budget); pieChart = (PieChart) findViewById(R.id.pie_budget); setDataChart(); } public void setDataChart(){ DBHelper db = new DBHelper (getApplicationContext()); List<Budget_PieChartList> names = db.getListPieChart(); pieChart.setRotationEnabled(true); pieChart.animateXY(1000, 1000); pieChart.setHoleRadius(36f); pieChart.setDescription(null); ArrayList<PieEntry> yVals = new ArrayList<>(); ArrayList<String> xVals = new ArrayList<>(); ArrayList<Integer> colors = new ArrayList<Integer>(); for (int c : ColorTemplate.VORDIPLOM_COLORS) colors.add(c); for (int c : ColorTemplate.JOYFUL_COLORS) colors.add(c); for (int c : ColorTemplate.COLORFUL_COLORS) colors.add(c); for (int c : ColorTemplate.LIBERTY_COLORS) colors.add(c); for (int c : ColorTemplate.PASTEL_COLORS) colors.add(c); colors.add(ColorTemplate.getHoloBlue()); float total_amount = db.getTotalAmount(); for(int index = 0; index<names.size(); index++){ float amount = (names.get(index).getAmount()/total_amount)*100f; yVals.add(new PieEntry(amount, index)); xVals.add(names.get(index).getName()); } PieDataSet dataSet = new PieDataSet(yVals, ""); dataSet.setSliceSpace(3f); dataSet.setSelectionShift(5f); dataSet.setColors(colors); PieData dataPie = new PieData(dataSet); dataPie.setValueFormatter(new PercentFormatter()); dataPie.setValueTextSize(12f); dataPie.setValueTextColor(Color.BLACK); Legend legend = pieChart.getLegend(); legend.setForm(Legend.LegendForm.CIRCLE); legend.setPosition(Legend.LegendPosition.LEFT_OF_CHART); pieChart.setData(dataPie); pieChart.highlightValues(null); pieChart.invalidate(); } 会创建一个新主题。

答案 1 :(得分:1)

  1.   

    traffic_measurement_handler是否在新线程中运行?

  2. POSIX threadssigev_notify = SIGEV_SIGNAL时,由于信号没有创建新线程。因此,在您的代码中,您不会创建新线程。

    1.   

      如何在处理程序运行时让回调停止?

    2. 您可以将信号设置为由运行回调的同一线程处理。

        

      POSIX.1区分了作为整体指向进程的信号的概念和指向单个线程的信号。

      阅读Unix pthreads and signals: per thread signal handlers