Scanf и printf с семафором System V - PullRequest
1 голос
/ 24 июня 2019

Я не могу понять, почему вывод моего кода следующий. Это не следует логике, которую я написал в программе. Я использую Семафор System V для синхронизации потоков друг с другом.

Эта программа должна просто запрашивать строки из стандартного ввода в «основной поток», и они должны записываться дочерними потоками в файлы, чье «имя пути» передается в argv. Для простоты я удалил эту часть и оставил только scanf и printf, которые были полностью перепутаны логикой программы!

Как мне это решить?

#define _GNU_SOURCE
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
#include <sys/syscall.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <signal.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#define fflush(stdin) while(getchar()!='\n') //REMOVE THIS
void *gestore(void *);
char buf[10];
struct info
{
        pthread_t tid[100];
        int v[100];
};
struct info TID;
union semun
{
        int val;
        struct semid_ds *buf;
        unsigned short *array;
        struct seminfo *__buf;
};
int indice;
int id_sem;
void *gestore(void *str)
{
        int fd, i, j;
        struct sembuf op[1];
        printf("Thread(%ld) CREATED\n",syscall(SYS_gettid));
        fflush(stdout);
        fd = open((char *)(str),O_CREAT|O_RDWR,0666);
        if(fd==-1)
        {
                printf("Error\n");
                return;
        }
        else
        {
                printf("File Opened\n");
                fflush(stdout);
        }
        repeat:
        op[0].sem_num=0;
        op[0].sem_op=-1;
        op[0].sem_op=0;
        semop(id_sem,op,1);
        printf("HELLO\n");
        fflush(stdout);
        for(i=0; i<5; i++)
        {
                if(write(fd,&(buf[2*i]),1)==-1)
                {
                        printf("ErroreWrite\n");
                        fflush(stdout);
                        return;
                }
                else
                {
                        printf("WRITED\n");
                        fflush(stdout);
                }

        }
        op[0].sem_num=1;
        op[0].sem_op=1;
        op[0].sem_op=0;
        semop(id_sem,op,1);
        goto repeat;

        if(close(fd)==-1)
        {
                printf("Errore close\n");
                return;
        }
        else
        {
                printf("File CLOSED\n");
                fflush(stdout);
        }

}



int main(int argc, char *argv[])
{
        if(argc<2)
        {
                printf("There must be at least 2 parameters\n");
                fflush(stdout);
                return -1;
        }
        int i;
        indice = argc;
        printf("Number of arguments:%d \n",argc);
        fflush(stdout);

        //SEM SYSTEM V

        union semun arg;
        struct sembuf op[1];
        id_sem = semget(6534,2,IPC_CREAT|0666);
        arg.val=0;
        semctl(id_sem,0,SETVAL,arg);
        arg.val=1;
        semctl(id_sem,1,SETVAL,arg);
        //////////////////////


        for(i=0; i<(argc-1); i++)
        {
                pthread_create(&(TID.tid[i]),NULL,gestore,argv[i+1]);
        }
        while(1)
        {
                op[0].sem_num=1;
                op[0].sem_op=-1;
                op[0].sem_op=0;
                semop(id_sem,op,1);

                for(i=0;i<5;i++)
                {
                        printf("Insert value(%d): \n",i);
                        fflush(stdout);
                        scanf("%c",&(buf[2*i]));
                        buf[2*i+1]='\0';
                        fflush(stdin);//USE while(getchar()!='\n');
                }

                op[0].sem_num=0;
                op[0].sem_op=1;
                op[0].sem_op=0;
                semop(id_sem,op,1);
        }

}

Вот мой вывод: (a, b, c, d, e, f, g - мой ввод со стандартного ввода)

Где моя строка "Вставить значение (% d) ..." ???

Number of arguments:4
a
Thread(1048) CREATED
Thread(1049) CREATED
Thread(1050) CREATED
b
File OPENED
c
File OPENED
d
File OPENED
e
f
HELLO
g
HELLO
h
WRITED
i
WRITED
l
WRITED
m
WRITED
n
WRITED
o
WRITED
p
WRITED
q
WRITED
e
WRITED
r
WRITED
s
a
s

Замена определенного мной макроса на fflus (stdin) следующего вида: while (getchar ()! = 'N'); полученный результат:

Number of arguments:4
Thread(1090) CREATED
Thread(1091) CREATED
Thread(1092) CREATED
File OPENED
File OPENED
HELLO
File OPENED
WRITED
HELLO
WRITED
WRITED
WRITED
WRITED
WRITED
WRITED
WRITED
WRITED
WRITED

В этом случае я получил эти выходные данные без отправки каких-либо входных символов.

Ответы [ 2 ]

1 голос
/ 24 июня 2019

Нашел тайну. Триплет:

  • оп [0] .sem_num = 0;
  • оп [0] .sem_op = -1;
  • оп [0] .sem_flg = 0;

Это везде было написано плохо следующим образом:

  • оп [0] .sem_num = 0;
  • оп [0] .sem_op = -1;
  • оп [0] .sem_op = 0; <--------- </strong>

Также с неверным определением, на которое указали другие пользователи, была катастрофа.

Спасибо всем!

0 голосов
/ 24 июня 2019

Не знаю, решит ли это вашу проблему, но ваш код СЕРЬЕЗНО некорректен с вашим define.Мало того, что это сбивает с толку читателей, которые знают, что промывка стандартного ввода - большой ноно.Он также изменяет все вызовы на fflush, независимо от аргумента.Вот программа Hello World для демонстрации:

#include <stdio.h>
#define fflush(stdin) printf("Hello, World!\n")

int main(void)
{
    // Will call above macro despite the fact that I'm trying to flush stdout
    fflush(stdout);
}

Если вы хотите использовать макрос, сделайте что-то вроде этого:

#define FLUSH_STDIN while(getchar()!='\n')

Но если у вас нет веских причин использоватьмакрос, используйте функцию:

void flush_stdin(void) { while(getchar()!='\n'); }

Я бы также рекомендовал не использовать идентификаторы, начинающиеся с подчеркивания (struct seminfo *__buf;), поскольку они зарезервированы в C.

...