■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
# 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, ¶m);
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, ¶m );
#endif
pthread_create( &threads[i],
&thread_attrs,
( void* (*)(void*) )Thread,
&thread_args[i] );
}
system("ps -l -L ");
while(1)sleep(1);
pthread_exit(0);
}
$ 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, ¶m);
if (s != 0)
handle_error_en(s, "pthread_getschedparam");
printf("%s\n", msg);
display_sched_attr(policy, ¶m);
}
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, ¶m);
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, ¶m);
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, ¶m);
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, ¶m);
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");
}
# ./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
'Linux System Programing' 카테고리의 다른 글
[리눅스 시스템 프로그래밍_Day5]세마포어, 뮤텍스 (0) | 2018.12.14 |
---|---|
[리눅스 시스템 프로그래밍_Day3]Multiplexed I/O, 프로세스 (0) | 2018.12.12 |
[리눅스 시스템 프로그래밍_Day1]Makefile 분석 (0) | 2018.12.11 |
[리눅스 시스템 프로그래밍_Day2]라이브러리, 파일 (0) | 2018.12.11 |