线程thread(day06)

作业1

司机: 接收售票员关门信号-->开车 //SIGUSR1
接收到站信号-->停车 //SIGINT
发送开门信号给售票员-->等待关门信号 //pause() 挂起进程
售票员:发送关门信号
接收开门信号-->开门 //SIGUSR2

#include 
#include 
#include   //fork ()
#include 
#include  //kill()
#include   //signal()

pid_t pid = -1;

//司机:到站停车  --> SIGINT  ctrl+c
//      关门开车  --> SIGUSR1
void handleDriver(int sig)
{
    if (SIGINT == sig)
    {
        printf("到站了...\\n");
        sleep(1);
        printf("司机开始停车...\\n");
        sleep(1);
        int ret = 0;
        ret = kill(pid, SIGUSR2);  //发送信号给售票员让她开门
        if (-1 == ret)
        {
            perror("kill");
        }
    }
    else if (SIGUSR1 == sig)
    {
        printf("司机开始开车...\\n");
        sleep(1);
        printf("车正在跑...\\n");   
        sleep(1);
    }
}
//售票员:开门 -->SIGUSR2
void handleConductor(int sig)
{
    if (SIGUSR2 == sig)
    {
        printf("售票员开门...\\n");
        sleep(1);
        printf("乘客上车...\\n");
        sleep(1);
        printf("售票员关门...\\n");
        sleep(1);
        kill(getppid(), SIGUSR1);  //售票员发送信号给司机开车
    }
}

int main(void)
{
    pid = fork();
    if (pid > 0)  //driver
    {
        signal(SIGINT, handleDriver);
        signal(SIGUSR1, handleDriver);
        printf("司机等待售票员做好开车准备...\\n");
        while (1)
        {
            pause();
        }   
    }
    else if (0 == pid)  //conductor
    {
        signal(SIGINT, SIG_IGN);
        signal(SIGUSR2, handleConductor);
        sleep(1);
        //发送一个开车信号让其开车
        kill(getppid(), SIGUSR1);
        while (1)
        {
            pause();    
        }   
    }
    else if (-1 == pid)
    {
        perror("fork");
        return -1;
    }

    return 0;
}

运行结果:


线程thread(day06)_第1张图片
1.PNG

创建线程

#include   //pthread_create()

#include 
#include  //strerror()
#include   //errno
#include 

void *thread_run(void *arg)
{
    while (1)
    {
        printf("this is thread_run...\\n");
        sleep(1);
    }

    return NULL;
}

int main(void)
{
    pthread_t thread;
    int ret = 0;
    ret = pthread_create(&thread, NULL, thread_run, NULL);
    if (0 != ret)
    {
        printf("errno:%d, error:%s\\n", ret, strerror(ret));
        return -1;
    }
    while (1)
    {
        printf("this is main...\\n");
        sleep(1);
    }

    return 0;
}

运行结果:

线程thread(day06)_第2张图片
2.PNG

pthread_arg.c

#include   //pthread_create()

#include 
#include  //strerror()
#include   //errno
#include 

typedef struct Student
{
    int iId;
    char caName[32];
    float fScore;
}Student;

void *thread_run(void *arg)
{
    while (1)
    {
        //printf("this is thread_run...arg = %d\\n", *(int *)arg);
        //printf("this is thread_run...arg = %d\\n", (int)arg);
        Student *pStu = (Student *)arg;
        printf("id:%d, name:%s, score:%.2f\\n"
               , pStu->iId, pStu->caName, pStu->fScore);
        sleep(1);
    }

    return NULL;
}

int main(void)
{
    pthread_t thread;
    int ret = 0;
    int iArg = 1888;
    //ret = pthread_create(&thread, NULL, thread_run, &iArg);
    //ret = pthread_create(&thread, NULL, thread_run, (void *)iArg);
    //ret = pthread_create(&thread, NULL, thread_run, (void *)1888);
    Student stu = {1001, "zhangsan", 89};
    ret = pthread_create(&thread, NULL, thread_run, &stu);
    //ret = pthread_create(&thread, NULL, thread_run, (void *)stu);  //error
    if (0 != ret)
    {
        printf("errno:%d, error:%s\\n", ret, strerror(ret));
        return -1;
    }
    while (1)
    {
        printf("this is main...\\n");
        pause();
    }

    return 0;
}

运行结果:


线程thread(day06)_第3张图片
1.PNG

pthread_cancel_exit.c

#include   //pthread_create()

#include 
#include  //strerror()
#include   //errno
#include 

void *thread_run(void *arg)
{
    //在线程函数中调用pthread_setcancelstate来设置
    //不同意结束线程请求,阻塞线程结束请求
    //直到线程允许接收线程结束请求
    pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
    while (1)
    {
        printf("this is thread_run...\\n");
        sleep(1);
        //break;
        //结束所属线程
        //pthread_exit(NULL);
    }

    return NULL;
}

int main(void)
{
    pthread_t thread;
    int ret = 0;
    ret = pthread_create(&thread, NULL, thread_run, NULL);
    if (0 != ret)
    {
        printf("errno:%d, error:%s\\n", ret, strerror(ret));
        return -1;
    }
    sleep(3);
    //发送一个结束线程请求给指定的线程
    //默认情况下,线程会同意该结束线程请求
    //还可以设置不同意
    //pthread_cancel(thread);
    
    //若存在主线程中,如果含有其他线程存在,
    //则阻塞等待线程的结束

    //若没有其他线程,则结束程序
    pthread_exit(NULL);
    while (1)
    {
        printf("this is main...\\n");
        sleep(1);
    }

    return 0;
}

运算结果:


线程thread(day06)_第4张图片
1.PNG

pthread_exit.c

#include   //pthread_create()

#include 
#include  //strerror()
#include   //errno
#include   //sleep()
#include   //exit()

//一个进程创建线程后,创建的线程从属于该进程
//不独立于进程,共享进程的所有资源

//线程是最小的执行单元,
//若一个进程没有创建线程,我们既可以把它看做是进程,也可以是相当于线程
//若一个进程创建线程后,我们可以将该进程称之为主线程
//一个进程可以创建多个线程,线程之间资源共享
void *thread_run(void *arg)
{
    int i = 0;
    while (1)
    {
        printf("this is thread_run...\\n");
        sleep(1);
        i++;
        if (5 == i)
        {
            //使用return 只能结束当前线程
            //return NULL;

            //会将该线程所属的进程挂掉,当然线程也会挂掉
            exit(1);
        }
    }

    return NULL;
}

int main(void)
{
    pthread_t thread;
    int ret = 0;
    ret = pthread_create(&thread, NULL, thread_run, NULL);
    if (0 != ret)
    {
        printf("errno:%d, error:%s\\n", ret, strerror(ret));
        return -1;
    }
    while (1)
    {
        printf("this is main...\\n");
        sleep(1);
    }

    return 0;
}

运算结果:


线程thread(day06)_第5张图片
1.PNG

pthread_join.c

#include   //pthread_create()

#include 
#include  //strerror()
#include   //errno
#include 

void *thread_run(void *arg)
{
    while (1)
    {
        printf("this is thread_run...\\n");
        sleep(1);
    }

    return NULL;
}

int main(void)
{
    pthread_t thread;
    int ret = 0;
    ret = pthread_create(&thread, NULL, thread_run, NULL);
    if (0 != ret)
    {
        printf("errno:%d, error:%s\\n", ret, strerror(ret));
        return -1;
    }
    //等待线程结束,若线程在运行,则阻塞等待
    //若线程结束,立即返回
    //第一个参数:要等待的线程
    //第二个参数:要来获得线程的返回值
    pthread_join(thread, NULL);
    while (1)
    {
        printf("this is main...\\n");
        sleep(1);
    }

    return 0;
}

运算结果:

线程thread(day06)_第6张图片
1.PNG

pthread_mutex.c

#include   //pthread_create()

#include 
#include  //strerror()
#include   //errno
#include 

pthread_mutex_t mutex;   //互斥量--锁

int g_iData = 0;

void *thread_run(void *arg)
{
    while (1)
    {
        //使用pthread_mutex_lock和pthread_mutex_unlock
        //使它们之间的语句合成原子操作

        //若其他线程没有释放该互斥量
        //则本线程阻塞等待
        //pthread_mutex_lock(&mutex);
        //pthread_mutex_trylock(&mutex);
        ++g_iData;
        printf("thread:data = %d\\n", g_iData);
        pthread_mutex_unlock(&mutex);
    }

    return NULL;
}

int main(void)
{
    //初始化互斥量,NULL表示使用默认属性初始化该互斥量
    pthread_mutex_init(&mutex, NULL);
    
    pthread_t thread;
    int ret = 0;
    ret = pthread_create(&thread, NULL, thread_run, NULL);
    if (0 != ret)
    {
        printf("errno:%d, error:%s\\n", ret, strerror(ret));
        return -1;
    }
    while (1)
    {
        pthread_mutex_lock(&mutex);
        ++g_iData;
        printf("main:data = %d\\n", g_iData);
        pthread_mutex_unlock(&mutex);
    }

    return 0;
}

运算结果:

线程thread(day06)_第7张图片
2.PNG

pthread_share

#include   //pthread_create()

#include 
#include  //strerror()
#include   //errno
#include 

int g_iData = 999;

void *thread_run(void *arg)
{
    //while (1)
    {
        printf("this is thread_run...iData = %d\\n", g_iData);
        g_iData++;
        //sleep(1);
    }

    return NULL;
}

int main(void)
{
    pthread_t thread;
    int ret = 0;
    ret = pthread_create(&thread, NULL, thread_run, NULL);
    if (0 != ret)
    {
        printf("errno:%d, error:%s\\n", ret, strerror(ret));
        return -1;
    }
    sleep(2);
    //  while (1)
    {
        printf("this is main...iData = %d\\n", g_iData);
//      sleep(1);
    }

    return 0;
}

运算结果:

线程thread(day06)_第8张图片
1.PNG

read_stu

#include 
#include   //write()  read()
#include    //errno
#include   //strerror()
/*open()*/
#include 
#include 
#include 

#include  //pthread_create

pthread_mutex_t mutex;

#define NAME_LEN 32
typedef struct Student
{
    int iId;
    char caName[NAME_re LEN];
    char cSex;
    float fScore;

}Student;

int myOpen(const char *pathname)
{
    int fd  = -1;
    if (NULL != pathname)
    {
        fd = open(pathname, O_RDONLY | O_CREAT
                  , S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
        if (-1 == fd)
        {
            printf("open error: %s\\n", strerror(errno));
        }
    }
    return fd;
}

int g_iSign = 0;

void *read_thread(void *arg)
{
    int fd = -1;
    fd = myOpen("stu.info");
    if (-1 != fd)
    {
        int ret = -1;
        Student *pStu = (Student *)arg;
        while (1)
        {
            if (0 == g_iSign)
            {
                pthread_mutex_lock(&mutex);
                memset(pStu, '\\0', sizeof(Student));
                ret = read(fd, pStu, sizeof(Student));
                if (0 == ret)
                {
                    printf("reached the file end\\n");
                    pthread_mutex_unlock(&mutex);
                    g_iSign = 1;
                    break;
                }
                else if (-1 == ret)
                {
                    printf("read error:%s\\n", strerror(errno));
                    pthread_mutex_unlock(&mutex);
                    g_iSign = 1;
                    break;
                }
                pthread_mutex_unlock(&mutex);
                g_iSign = 1;
            }
        }
        close(fd);
    }   

    return NULL;
}

void *print_thread(void *arg)
{
    Student *pStu = (Student *)arg;
    int i = 0;
    while (1)
    {
        if (1 == g_iSign)
        {
            pthread_mutex_lock(&mutex);
            if (0 == pStu->iId)
            {
                pthread_mutex_unlock(&mutex);
                break;
            }
        
            printf("id:%d, name:%s, sex:%c, score:%.1f\\n"
                   , pStu->iId, pStu->caName
                   , pStu->cSex, pStu->fScore);
        
            pthread_mutex_unlock(&mutex);
            g_iSign = 0;
        }
    }

    return NULL;
}

int main(void)
{
    pthread_mutex_init(&mutex, NULL);

    Student stu;
    pthread_t pthr_read;
    pthread_t pthr_show;

    pthread_create(&pthr_read, NULL, read_thread, &stu);
    pthread_create(&pthr_show, NULL, print_thread, &stu);

    pthread_join(pthr_read, NULL);
    pthread_join(pthr_show, NULL);

    return 0;
}

运算结果:


线程thread(day06)_第9张图片
3.PNG

write_stu.c

#include 
#include   //write()
#include    //errno
#include   //strerror()
/*open()*/
#include 
#include 
#include 

#define NAME_LEN 32
typedef struct Student
{
    int iId;
    char caName[NAME_LEN];
    char cSex;
    float fScore;

}Student;

int myOpen(const char *pathname)
{
    int fd  = -1;
    if (NULL != pathname)
    {
        fd = open(pathname, O_WRONLY | O_CREAT | O_TRUNC
                  , S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
        if (-1 == fd)
        {
            printf("open error: %s\\n", strerror(errno));
        }
    }
    return fd;
}

int main(void)
{
    int fd = -1;
    fd = myOpen("stu.info");
    if (-1 != fd)
    {
        Student stu[6] = {{1001, "zhangsan", 'f', 99}
                          , {1002, "lisi", 'm', 79}
                          , {1003, "wangwu", 'f', 89}
                          , {1004, "zhaoliu", 'm', 69}
                          , {1005, "xiaoqi", 'm', 79}
                          , {1006, "laoba", 'f', 89}};
        int ret = -1;
        int i = 0;
        for (; i < 6; i++)
        {
            ret = write(fd, stu+i, sizeof(Student));
            if (-1 == ret)
            {
                printf("write error: %s\\n", strerror(errno));
            }
            else
            {
                printf("write %d bytes to file\\n", ret);
            }
        }
    }   

    return 0;
}
线程thread(day06)_第10张图片
1.PNG

sem_read_stu.c

#include 
#include   //write()  read()
#include    //errno
#include   //strerror()
/*open()*/
#include 
#include 
#include 

#include  //pthread_create
#include   

pthread_mutex_t mutex;

sem_t read_sem;  //整形 
sem_t show_sem;

#define NAME_LEN 32
typedef struct Student
{
    int iId;
    char caName[NAME_LEN];
    char cSex;
    float fScore;

}Student;

int myOpen(const char *pathname)
{
    int fd  = -1;
    if (NULL != pathname)
    {
        fd = open(pathname, O_RDONLY | O_CREAT
                  , S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
        if (-1 == fd)
        {
            printf("open error: %s\\n", strerror(errno));
        }
    }
    return fd;
}

void *read_thread(void *arg)
{
    int fd = -1;
    fd = myOpen("stu.info");
    if (-1 != fd)
    {
        int ret = -1;
        Student *pStu = (Student *)arg;
        while (1)
        {
            //如果read_sem大于0,接着往下执行,并且将该变量减一
            //如果read_sem等于0,则阻塞,直到该值大于0
            sem_wait(&read_sem);
            
            pthread_mutex_lock(&mutex);
            
            memset(pStu, '\\0', sizeof(Student));
            ret = read(fd, pStu, sizeof(Student));
            if (0 == ret)
            {
                printf("reached the file end\\n");
                pthread_mutex_unlock(&mutex);
                sem_post(&show_sem);
                break;
            }
            else if (-1 == ret)
            {
                printf("read error:%s\\n", strerror(errno));
                pthread_mutex_unlock(&mutex);
                sem_post(&show_sem);
                break;
            }
            pthread_mutex_unlock(&mutex);
            //将信号量的值加一
            sem_post(&show_sem);
        }
    }
    close(fd);

    return NULL;
}

void *print_thread(void *arg)
{
    Student *pStu = (Student *)arg;
    int i = 0;
    while (1)
    {
        {
            //如果show_sem大于0,接着往下执行,并且将该变量减一
            //如果show_sem等于0,则阻塞,直到该值大于0
            sem_wait(&show_sem);
            pthread_mutex_lock(&mutex);
            if (0 == pStu->iId)
            {
                pthread_mutex_unlock(&mutex);
                sem_post(&read_sem);
                break;
            }
        
            printf("id:%d, name:%s, sex:%c, score:%.1f\\n"
                   , pStu->iId, pStu->caName
                   , pStu->cSex, pStu->fScore);
        
            pthread_mutex_unlock(&mutex);
            //将信号量的值加一
            sem_post(&read_sem);
        }
    }

    return NULL;
}

int main(void)
{
    pthread_mutex_init(&mutex, NULL);

    //初始化信号量
    sem_init(&read_sem, 0, 1);  //将read_sem值置为1
    sem_init(&show_sem, 0, 0);  //将show_sem值置为0

    Student stu;
    pthread_t pthr_read;
    pthread_t pthr_show;

    pthread_create(&pthr_read, NULL, read_thread, &stu);
    pthread_create(&pthr_show, NULL, print_thread, &stu);

    pthread_join(pthr_read, NULL);
    pthread_join(pthr_show, NULL);

    return 0;
}

运算结果:


线程thread(day06)_第11张图片
1.PNG

write_stu.c

#include 
#include   //write()
#include    //errno
#include   //strerror()
/*open()*/
#include 
#include 
#include 

#define NAME_LEN 32
typedef struct Student
{
    int iId;
    char caName[NAME_LEN];
    char cSex;
    float fScore;

}Student;

int myOpen(const char *pathname)
{
    int fd  = -1;
    if (NULL != pathname)
    {
        fd = open(pathname, O_WRONLY | O_CREAT | O_TRUNC
                  , S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
        if (-1 == fd)
        {
            printf("open error: %s\\n", strerror(errno));
        }
    }
    return fd;
}

int main(void)
{
    int fd = -1;
    fd = myOpen("stu.info");
    if (-1 != fd)
    {
        Student stu[6] = {{1001, "zhangsan", 'f', 99}
                          , {1002, "lisi", 'm', 79}
                          , {1003, "wangwu", 'f', 89}
                          , {1004, "zhaoliu", 'm', 69}
                          , {1005, "xiaoqi", 'm', 79}
                          , {1006, "laoba", 'f', 89}};
        int ret = -1;
        int i = 0;
        for (; i < 6; i++)
        {
            ret = write(fd, stu+i, sizeof(Student));
            if (-1 == ret)
            {
                printf("write error: %s\\n", strerror(errno));
            }
            else
            {
                printf("write %d bytes to file\\n", ret);
            }
        }
    }   

    return 0;
}

运算结果:


线程thread(day06)_第12张图片
1.PNG

think-eat.c

/*semget()*/
#include 
#include 
#include 

#include  //perror()
#include  //fork()
#include   //printf()

union semun 
{
    int val;    /* Value for SETVAL */
    struct semid_ds *buf;    /* Buffer for IPC_STAT,IPC_SET */
    unsigned short  *array;  /* Array for GETALL, SETALL */
    struct seminfo  *__buf;  /* Buffer for IPC_INFO(Linux-specific) */                                                      
};

#if 0
int semop(int semid, struct sembuf *sops, unsigned nsops);

参数
semid:信号集的识别码,可通过semget获取。
sops:指向存储信号操作结构的数组指针,信号操作结构的原型如下
struct sembuf
{
        unsigned short sem_num; /* semaphore number */
        short sem_op; /* semaphore operation */
        short sem_flg; /* operation flags */
};
这三个字段的意义分别为:
sem_num:操作信号在信号集中的编号,第一个信号的编号是0。

sem_op:
   1, 如果其值为正数,该值会加到现有的信号内含值中。
      通常用于释放所控资源的使用权;
   2, 如果sem_op的值为负数,而其绝对值又大于信号的现值,
      操作将会阻塞,直到信号值大于或等于sem_op的绝对值。
      通常用于获取资源的使用权;
   3, 如果sem_op的值为0,如果没有设置IPC_NOWAIT,
      则调用该操作的进程或者线程将暂时睡眠,直到信号量的值为0;      否则,进程或者线程不会睡眠,函数返回错误EAGAIN。

sem_flg:信号操作标志,可能的选择有两种
   1, IPC_NOWAIT //对信号的操作不能满足时,semop()不会阻塞,
      并立即返回,同时设定错误信息。
   2, SEM_UNDO //程序结束时(不论正常或不正常),
      保证信号值会被重设为semop()调用前的值。
      这样做的目的在于避免程序在异常情况下结束时
      未将锁定的资源解锁,造成该资源永远锁定。

nsops:信号操作结构的数量,恒大于或等于1。
#endif

void getChopsticks(int iNum, int *semfd)
{
    int iLeft = iNum;
    int iRight = (iNum + 1)%5;

    struct sembuf semope[2] = {{iLeft, -1, 0}
                               , {iRight, -1, 0}};
    semop(*semfd, semope, 2);
}

void putChopsticks(int iNum, int *semfd)
{
    int iLeft = iNum;
    int iRight = (iNum + 1)%5;

    struct sembuf semope[2] = {{iLeft, 1, 0}
                               , {iRight, 1, 0}};
    semop(*semfd, semope, 2);
}

void thinkAndEat(int iNum, int *semfd)
{
    while (1)
    {
        printf("%d say: I am thinking...\\n", iNum);
        /*拿筷子吃饭*/
        getChopsticks(iNum, semfd);
        sleep(1);
        printf("%d say: I am eatting...\\n", iNum);
        /*放下筷子*/
        putChopsticks(iNum, semfd);
        printf("%d say: I am put chopsticks...\\n", iNum);
        sleep(1);
    }
}

int main(void)
{
    int semfd = -1;
    //获得信号量集的标识,若信号量集不存在则创建
    semfd = semget(0x1024, 5, IPC_CREAT | 0777);
    if (-1 == semfd)
    {
        perror("semget");
        return -1;
    }

    //对信号集中的信号量赋值
    union semun sem;
    sem.val = 1;
    int i = 0;
    for (; i < 5; i++)
    {
        if (-1 == semctl(semfd, i, SETVAL, sem))
        {
            perror("semctl");
            return -1;
        }
    }

    //创建五个哲学家进程
    int num = 0;  //表示第几个哲学家
    pid_t pid = -1;
    for (i = 0; i < 4; i++)
    {
        pid = fork();
        if (pid > 0)  //parent
        {
            num = 4;
        }
        else if (0 == pid) //child
        {
            num = i;
            break;
        }
        else if (-1 == pid) //error
        {
            return -1;
        }
    }
    thinkAndEat(num, &semfd);

    return 0;
}

运算结果:

线程thread(day06)_第13张图片
2.PNG

你可能感兴趣的:(线程thread(day06))