■Thread




*스레드 생성 및 종료


//    pthread_test_q.c    //

#include <stdio.h>

#include <pthread.h>


int thread_args[3] = { 0, 1, 2 };                        /*스레드가 사용할 인자*/


void* Thread( void *arg )

{

    int i;

    for ( i=0; i<3; i++ )

        printf( "thread %d: %dth iteration\n", *(int*)arg, i );


//while(1); // TODO: hold here and try $ps -L


pthread_exit(0);

}


int main( void )

{

    int i, clock_get;

    pthread_t threads[3];         /*스레드 아이디 변수 */

    

    for ( i=0; i<3; i++ ) 

        // TODO: create a thread having Thread function 

        pthread_create( &threads[i],                

                        NULL,                      

                        ( void* (*)(void*) )Thread,

                        &thread_args[i] );

    

    while(1)sleep(1);

    

    //TODO: exit

    pthread_exit(0);

}


# cc pthread_test_q.c -lpthread

# ./a.out 


thread 2: 0th iteration

thread 2: 1th iteration

thread 2: 2th iteration

thread 1: 0th iteration

thread 1: 1th iteration

thread 1: 2th iteration

thread 0: 0th iteration

thread 0: 1th iteration

thread 0: 2th iteration

.....


thread 함수에 while(1); 
main에 while(1)sleep(1);

# ./a.out &
# ps -L

  PID   LWP TTY          TIME CMD
14150 14150 pts/0    00:00:00 a.out 
14150 14151 pts/0    00:00:01 a.out
14150 14152 pts/0    00:00:01 a.out
14150 14153 pts/0    00:00:01 a.out

thread 함수에 while(1); 
main에 while(1)sleep(1); 뺀 경우
# ./a.out &
# ps -L

  PID   LWP TTY          TIME CMD
14150 14150 pts/0    00:00:00 a.out <defunct>
14150 14151 pts/0    00:00:01 a.out
14150 14152 pts/0    00:00:01 a.out
14150 14153 pts/0    00:00:01 a.out

thread 함수에 while(1); 
main에 while(1)sleep(1);     pthread_exit(0);   뺀 경우


# ps -L

  PID   LWP TTY          TIME CMD

14061 14061 pts/0    00:00:00 bash

14439 14439 pts/0    00:00:00 ps


부모 프로세스가 끝나면 나머지 스레드들도 같이 끝난다.







*스레드 속성


//    pthread_attr_a.c    //

 

#include <stdio.h>

#include <pthread.h>

#include <sched.h>

#include <unistd.h>

#include <sys/types.h>


int thread_args[3] = { 0, 1, 2 };


void* Thread( void *arg )

{

    int i;

//    nice(10); // only for SCHED_NORMAL

for ( i=0; i<100; i++ ){

        printf( "%d", *(int*)arg);

    }


fflush(stdout); // try if you have not displayed 2s all enough !

//system("ps -l -L ");


sleep(100); //sleep for probe


    pthread_exit(0);  

}


int main( void ) {

    int i;

    pthread_t threads[3];

int policy;

  pid_t mypid;

    /*TODO: thread attribute variable here */

    pthread_attr_t  thread_attrs;


    /*TODO: thread schedule parameter here */

    struct sched_param  param;


mypid = getpid();


policy = sched_getscheduler(0); // get policy of self

printf("current policy is : %s \n", (policy==0) ? "SCHED_NORMAL" : (policy==1) ? "SCHED_FIFO" :(policy==2) ? "SCHED_RR" : "else" );

/*

#define SCHED_NORMAL            0

#define SCHED_FIFO              1

#define SCHED_RR                2

#define SCHED_BATCH             3

*/


#if 1

param.sched_priority = 30; /* 1 - 99 */

sched_setscheduler(mypid, SCHED_FIFO, &param);


policy = sched_getscheduler(0); // get policy of self

printf("current policy is : %s \n", (policy==0) ? "SCHED_NORMAL" : (policy==1) ? "SCHED_FIFO" :(policy==2) ? "SCHED_RR" : "else" );

#endif

    for ( i=0; i<3; i++ ) {

#if 1


/*

2 options of  : inherit( default: follow Mom's ) or explicit ( my own )

**/


/*TODO: initialize thread atrribute variable here */ 

        pthread_attr_init( &thread_attrs );


        /*TODO: set schedule policy : round-robin here */ 

        pthread_attr_setschedpolicy( &thread_attrs, SCHED_FIFO );  /* you can't change under inherit. just follow leader thread's **/


        /*TODO: set thread priority : 15 */   /* you can't change under inherit. just follow leader thread's **/

        param.sched_priority = 15;

        pthread_attr_setschedparam( &thread_attrs, &param );

#endif

        pthread_create( &threads[i], 

                        &thread_attrs, 

                        ( void* (*)(void*) )Thread, 

                        &thread_args[i] );


    }


    

system("ps -l -L ");

while(1)sleep(1);

    pthread_exit(0); 

}



<    user mode    >

$ cc pthread_attr_a.c -lpthread


$ ./a.out 

current policy is : SCHED_NORMAL 

current policy is : SCHED_NORMAL 

222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222211111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111110000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000F S   UID   PID  PPID   LWP  C PRI  NI ADDR SZ WCHAN  TTY          TIME CMD

0 S  1001  1430  1428  1430  0  80   0 -  1518 wait   pts/0    00:00:00 bash

0 S  1001  2151  1430  2151  0  80   0 -  6610 wait   pts/0    00:00:00 a.out

1 S  1001  2151  1430  2152  0  80   0 -  6610 hrtime pts/0    00:00:00 a.out

1 S  1001  2151  1430  2153  0  80   0 -  6610 hrtime pts/0    00:00:00 a.out

1 S  1001  2151  1430  2154  0  80   0 -  6610 hrtime pts/0    00:00:00 a.out

0 S  1001  2155  2151  2155  0  80   0 -   457 wait   pts/0    00:00:00 sh

0 R  1001  2156  2155  2156  0  80   0 -   625 -      pts/0    00:00:00 ps


 nice(10); 가 있으면


$ ./a.out 

current policy is : SCHED_NORMAL 

current policy is : SCHED_NORMAL                 ==>user mode라서 바뀌지 않는다.

222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222211111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111110000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000

F S   UID   PID  PPID   LWP  C PRI  NI ADDR SZ WCHAN  TTY          TIME CMD

0 S  1001  1430  1428  1430  1  80   0 -  1518 wait   pts/0    00:00:00 bash

0 S  1001  1481  1430  1481  0  80   0 -  6610 wait   pts/0    00:00:00 a.out

1 S  1001  1481  1430  1482  0  90  10 -  6610 hrtime pts/0    00:00:00 a.out

1 S  1001  1481  1430  1483  0  90  10 -  6610 hrtime pts/0    00:00:00 a.out

1 S  1001  1481  1430  1484  0  90  10 -  6610 hrtime pts/0    00:00:00 a.out

0 S  1001  1485  1481  1485  0  80   0 -   457 wait   pts/0    00:00:00 sh

0 R  1001  1486  1485  1486  0  80   0 -   625 -      pts/0    00:00:00 ps


<    supervisor mode    >


# ./a.out 

current policy is : SCHED_NORMAL 

current policy is : SCHED_FIFO 

000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111112222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222

F S   UID   PID  PPID   LWP  C PRI  NI ADDR SZ WCHAN  TTY          TIME CMD

4 S     0  2157  1430  2157  3  80   0 -  1530 wait   pts/0    00:00:00 bash

4 S     0  2172  2157  2172  0  29   - -  6610 wait   pts/0    00:00:00 a.out

1 S     0  2172  2157  2173  0  29   - -  6610 hrtime pts/0    00:00:00 a.out

1 S     0  2172  2157  2174  0  29   - -  6610 hrtime pts/0    00:00:00 a.out

1 S     0  2172  2157  2175  0  29   - -  6610 hrtime pts/0    00:00:00 a.out

0 S     0  2176  2172  2176  0  29   - -   457 wait   pts/0    00:00:00 sh

4 R     0  2177  2176  2177  0  29   - -   625 -      pts/0    00:00:00 ps


















//    pthread_attr_a3.c    // 


/*

refer To:

https://www.systutorials.com/docs/linux/man/3-pthread_setschedparam/


*/


#include <pthread.h>

#include <stdio.h>

#include <stdlib.h>

#include <unistd.h>

#include <errno.h>


#define handle_error_en(en, msg) \

        do { errno = en; perror(msg); exit(EXIT_FAILURE); } while (0)


static void

usage(char *prog_name, char *msg)

{

    if (msg != NULL)

        fputs(msg, stderr);


    fprintf(stderr, "Usage: %s [options]\n", prog_name);

    fprintf(stderr, "Options are:\n");

#define fpe(msg) fprintf(stderr, "\t%s", msg);          /* Shorter */

    fpe("-a<policy><prio> Set scheduling policy and priority in\n");

    fpe("                 thread attributes object\n");

    fpe("                 <policy> can be\n");

    fpe("                     f  SCHED_FIFO\n");

    fpe("                     r  SCHED_RR\n");

    fpe("                     o  SCHED_OTHER\n");

    fpe("-A               Use default thread attributes object\n");

    fpe("-i {e|s}         Set inherit scheduler attribute to\n");

    fpe("                 'explicit' or 'inherit'\n");

    fpe("-m<policy><prio> Set scheduling policy and priority on\n");

    fpe("                 main thread before pthread_create() call\n");

    exit(EXIT_FAILURE);

}


static int

get_policy(char p, int *policy)

{

    switch (p) {

    case 'f': *policy = SCHED_FIFO;     return 1;

    case 'r': *policy = SCHED_RR;       return 1;

    case 'o': *policy = SCHED_OTHER;    return 1;

    default:  return 0;

    }

}


static void

display_sched_attr(int policy, struct sched_param *param)

{

    printf("    policy=%s, priority=%d\n",

            (policy == SCHED_FIFO)  ? "SCHED_FIFO" :

            (policy == SCHED_RR)    ? "SCHED_RR" :

            (policy == SCHED_OTHER) ? "SCHED_OTHER" :

            "???",

            param->sched_priority);

}


static void

display_thread_sched_attr(char *msg)

{

    int policy, s;

    struct sched_param param;


    s = pthread_getschedparam(pthread_self(), &policy, &param);

    if (s != 0)

        handle_error_en(s, "pthread_getschedparam");


    printf("%s\n", msg);

    display_sched_attr(policy, &param);

}


static void *

thread_start(void *arg)

{

    display_thread_sched_attr("Scheduler attributes of new thread");


    return NULL;

}


int

main(int argc, char *argv[])

{

    int s, opt, inheritsched, use_null_attrib, policy;

    pthread_t thread;

    pthread_attr_t attr;

    pthread_attr_t *attrp;

    char *attr_sched_str, *main_sched_str, *inheritsched_str;

    struct sched_param param;


    /* Process command-line options */


    use_null_attrib = 0;

    attr_sched_str = NULL;

    main_sched_str = NULL;

    inheritsched_str = NULL;


    while ((opt = getopt(argc, argv, "a:Ai:m:")) != -1) {

        switch (opt) {

        case 'a': attr_sched_str = optarg;      break;

        case 'A': use_null_attrib = 1;          break;

        case 'i': inheritsched_str = optarg;    break;

        case 'm': main_sched_str = optarg;      break;

        default:  usage(argv[0], "Unrecognized option\n");

        }

    }


    if (use_null_attrib &&

            (inheritsched_str != NULL || attr_sched_str != NULL))

        usage(argv[0], "Can't specify -A with -i or -a\n");


    /* Optionally set scheduling attributes of main thread,

       and display the attributes */


    if (main_sched_str != NULL) {

        if (!get_policy(main_sched_str[0], &policy))

            usage(argv[0], "Bad policy for main thread (-s)\n");

        param.sched_priority = strtol(&main_sched_str[1], NULL, 0);


        s = pthread_setschedparam(pthread_self(), policy, &param);

        if (s != 0)

            handle_error_en(s, "pthread_setschedparam");

    }

    display_thread_sched_attr("Scheduler settings of main thread");

    printf("\n");


    /* Initialize thread attributes object according to options */


    attrp = NULL;


    if (!use_null_attrib) {

        s = pthread_attr_init(&attr);

        if (s != 0)

            handle_error_en(s, "pthread_attr_init");

        attrp = &attr;

    }


    if (inheritsched_str != NULL) {

        if (inheritsched_str[0] == 'e')

            inheritsched = PTHREAD_EXPLICIT_SCHED;

        else if (inheritsched_str[0] == 'i')

            inheritsched = PTHREAD_INHERIT_SCHED;

        else

            usage(argv[0], "Value for -i must be 'e' or 'i'\n");


        s = pthread_attr_setinheritsched(&attr, inheritsched);

        if (s != 0)

            handle_error_en(s, "pthread_attr_setinheritsched");

    }


    if (attr_sched_str != NULL) {

        if (!get_policy(attr_sched_str[0], &policy))

            usage(argv[0],

                    "Bad policy for 'attr' (-a)\n");

        param.sched_priority = strtol(&attr_sched_str[1], NULL, 0);


        s = pthread_attr_setschedpolicy(&attr, policy);

        if (s != 0)

            handle_error_en(s, "pthread_attr_setschedpolicy");

        s = pthread_attr_setschedparam(&attr, &param);

        if (s != 0)

            handle_error_en(s, "pthread_attr_setschedparam");

    }


    /* If we initialized a thread attributes object, display

       the scheduling attributes that were set in the object */


    if (attrp != NULL) {

        s = pthread_attr_getschedparam(&attr, &param);

        if (s != 0)

            handle_error_en(s, "pthread_attr_getschedparam");

        s = pthread_attr_getschedpolicy(&attr, &policy);

        if (s != 0)

            handle_error_en(s, "pthread_attr_getschedpolicy");


        printf("Scheduler settings in 'attr'\n");

        display_sched_attr(policy, &param);


        s = pthread_attr_getinheritsched(&attr, &inheritsched);

        printf("    inheritsched is %s\n",

                (inheritsched == PTHREAD_INHERIT_SCHED)  ? "INHERIT" :

                (inheritsched == PTHREAD_EXPLICIT_SCHED) ? "EXPLICIT" :

                "???");

        printf("\n");

    }


    /* Create a thread that will display its scheduling attributes */


    s = pthread_create(&thread, attrp, &thread_start, NULL);

    if (s != 0)

        handle_error_en(s, "pthread_create");


    /* Destroy unneeded thread attributes object */


    s = pthread_attr_destroy(&attr);

    if (s != 0)

        handle_error_en(s, "pthread_attr_destroy");


    s = pthread_join(thread, NULL);

    if (s != 0)

        handle_error_en(s, "pthread_join");


    exit(EXIT_SUCCESS);

}





<    supervisor mode    >


# ./a.out -mf10 -ar20 -i e

Scheduler settings of main thread

    policy=SCHED_FIFO, priority=10


Scheduler settings in 'attr'

    policy=SCHED_RR, priority=20

    inheritsched is EXPLICIT


Scheduler attributes of new thread

    policy=SCHED_RR, priority=20



# ./a.out -mf10 -ar20 -i i

Scheduler settings of main thread

    policy=SCHED_FIFO, priority=10


Scheduler settings in 'attr'

    policy=SCHED_RR, priority=20

    inheritsched is INHERIT


Scheduler attributes of new thread

    policy=SCHED_FIFO, priority=10




*스레드 join


//    pthread_join_a.c    // 

#include <pthread.h>

#include <stdlib.h>

#include <unistd.h>

#include <stdio.h>


void *thread_function(void *arg) { 

     int i; 

     for ( i=0; i<10; i++ ) { 

         printf("Thread : says hi! [%d]\n",i ); 

         sleep(1); 

     } 

     return NULL; 

}


int main(void) {


    pthread_t mythread;


    if ( pthread_create( &mythread, NULL, thread_function, NULL) ) {

       printf("error creating thread."); 

       abort(); 

    }


    if ( pthread_join ( mythread, NULL ) ) { //TODO: join mythread 

         printf("error joining thread."); 

         abort(); 

    }


    printf("main: finally joined \n");


}



join : mythread로 시작된 쓰레드가 종료되는걸 기다린다.

# ./a.out 

Thread : says hi! [0]

Thread : says hi! [1]

Thread : says hi! [2]

Thread : says hi! [3]

Thread : says hi! [4]

Thread : says hi! [5]

Thread : says hi! [6]

Thread : says hi! [7]

Thread : says hi! [8]

Thread : says hi! [9]

main: finally joined 



+ Recent posts