Stdinning o'rnini olgan fayl identifikatorini yaratish (Select ())

Klaviatura kiritmasdan ko'p mijozli Unix domen soketi bilan aloqa o'rnatishni unutib, stdin-ning o'rnini bosadigan fayl identifikatorini yaratmoqchiman.

With a multi-client socket, you have to add the stdin's file descriptor (which is 0, with FD_SET(0, &readfds)) to readfds in order to send the keyboard input (FD_ISSET(0, &readfds)) to the server. Since I don't want to write everytime I launch my client, I want to replace this file descriptor by a custom one (by writing to this file from another program).

Ikki dastur yaratish uchun fayl identifikatorini yarating ni sinab ko'rdim:

Fayl identifikatoriga yozadigan:

int main() {
    char buffer[] = "test";
    int fd = open("sample.dat", O_WRONLY | O_CREAT, 0666);
    dup2(fd, 5);

    if(write(5, buffer, 4) < 0)
        fprintf(stderr, "write %s\n", strerror(errno));

    close(5);    
    return 0;
}

Undan boshqasini o'qiydi:

int main() {
    char buffer[4];
    int fd = open("sample.dat", O_RDONLY);
    dup2(fd, 5);

    for(;;) {
        if(read(5, buffer, 4) < 0)
            fprintf(stderr, "read %s\n", strerror(errno));

        printf("%s\n", buffer);
        sleep(1);
    }

    return 0;
}

My question is: is it possible to make this file descriptor as stdin-like ? I mean actually my second program read "test" endlessly because (of course) sample.dat still contains "test" but I want to delete it once it has been read.

0
Siz nima so'rayotganingiz juda aniq emas - "stdin-like" bilan nimani nazarda tutasiz?
qo'shib qo'ydi muallif Chris Turner, manba
Stdin'dan biror narsa o'qiganingizda @ chrisTurner siz o'qiganingizdan so'ng uni faqat bir marta o'qib chiqasiz, chunki u stdin "yo'q qilmoqda"/"tozalaydi" (men buni qanday ishlashini aniq bilmayman)
qo'shib qo'ydi muallif Raphaël, manba
Stdin'dan biror narsa o'qiganingizda @ chrisTurner siz o'qiganingizdan so'ng uni faqat bir marta o'qib chiqasiz, chunki u stdin "yo'q qilmoqda"/"tozalaydi" (men buni qanday ishlashini aniq bilmayman)
qo'shib qo'ydi muallif Raphaël, manba

6 javoblar

Yes. You can use pipes for this: https://linux.die.net/man/2/pipe

Yoki FIFO'lar: https://linux.die.net/man/3/mkfifo FIFO'lardan foydalanish fayl tizimida fayl yaratadi va u mijoz va server jarayoni orqali muloqot qilish uchun ochilishi mumkin.

0
qo'shib qo'ydi

Yes. You can use pipes for this: https://linux.die.net/man/2/pipe

Yoki FIFO'lar: https://linux.die.net/man/3/mkfifo FIFO'lardan foydalanish fayl tizimida fayl yaratadi va u mijoz va server jarayoni orqali muloqot qilish uchun ochilishi mumkin.

0
qo'shib qo'ydi

Muammo doim siz "test" da o'qiyotganingiz emas, balki uni read() ga to'g'ri kelmaydigan qilib yuborishingiz kerak. Agar siz xatolikni qaytarmaganligini tekshirayotgan bo'lsangiz, qancha bayt o'qilganligini bilmayapsiz. read() o'qilgan satrni null-terminatsiyalashtirmaydi, shuning uchun siz aslida qaytish qiymatini saqlab qo'ying va NULni buferda joylashtirish uchun foydalaning. Aks holda, buferda hech narsa o'zgarmas ekan, u xuddi shu matnni qayta va qayta o'qiyotganingizda paydo bo'ladi.

    int err=read(fd, buffer, 4);
    if(err < 0)
        {
        fprintf(stderr, "read %s\n", strerror(errno));
        }
    else
        {
        buffer[err]='\0';
        }

Agar siz bu o'zgarishlarni amalga oshirsangiz, siz faqat "sinov" da bir marta o'qib chiqdingiz va bundan keyin hech narsa o'qimaysiz.

Eslatma: Sizga dup2() ga qo'ng'iroqlar kerak emas, bu fayl identifikatorini ma'lum qiymatga nusxalash uchun. Faqat fd dan foydalanishingiz mumkin, chunki bu ma'lumotlarni o'qish/yozish uchun qo'ng'iroqlaringizda.

0
qo'shib qo'ydi
Ha, ha, u ishlayapti rahmat, u hech qachon "test" o'qimaydi, lekin men "tess" ni yozish bilan fdni yangilaganimda, u biror narsani o'qishni davom ettiradi. CTRL + C bo'lsa, uni faqat "tess" o'qiydi va qayta ishga tushiradi
qo'shib qo'ydi muallif Raphaël, manba

Muammo doim siz "test" da o'qiyotganingiz emas, balki uni read() ga to'g'ri kelmaydigan qilib yuborishingiz kerak. Agar siz xatolikni qaytarmaganligini tekshirayotgan bo'lsangiz, qancha bayt o'qilganligini bilmayapsiz. read() o'qilgan satrni null-terminatsiyalashtirmaydi, shuning uchun siz aslida qaytish qiymatini saqlab qo'ying va NULni buferda joylashtirish uchun foydalaning. Aks holda, buferda hech narsa o'zgarmas ekan, u xuddi shu matnni qayta va qayta o'qiyotganingizda paydo bo'ladi.

    int err=read(fd, buffer, 4);
    if(err < 0)
        {
        fprintf(stderr, "read %s\n", strerror(errno));
        }
    else
        {
        buffer[err]='\0';
        }

Agar siz bu o'zgarishlarni amalga oshirsangiz, siz faqat "sinov" da bir marta o'qib chiqdingiz va bundan keyin hech narsa o'qimaysiz.

Eslatma: Sizga dup2() ga qo'ng'iroqlar kerak emas, bu fayl identifikatorini ma'lum qiymatga nusxalash uchun. Faqat fd dan foydalanishingiz mumkin, chunki bu ma'lumotlarni o'qish/yozish uchun qo'ng'iroqlaringizda.

0
qo'shib qo'ydi
Ha, ha, u ishlayapti rahmat, u hech qachon "test" o'qimaydi, lekin men "tess" ni yozish bilan fdni yangilaganimda, u biror narsani o'qishni davom ettiradi. CTRL + C bo'lsa, uni faqat "tess" o'qiydi va qayta ishga tushiradi
qo'shib qo'ydi muallif Raphaël, manba

Agar men to'g'ri tushunsam, faqat stdinni o'qiy oladigan dasturga bog'lanmoqchisan. Stdin yozishning ikki yo'li bor: birinchi usul klaviaturadan foydalanish, ikkinchisidir write() dan foydalanish.

#include 
#include 

int         main(void)
{
    char    *s = "what you want to write";
    write(STDIN_FILENO, s, strlen(s));
    return (0);
}

Ushbu dastur sizning klaviaturangiz bilan bir xil tarzda yozishni istagan stdin-da yozadi. Bundan tashqari, siz buyruq qatori interfeysida chop etilgan satrni ko'rasiz.

0
qo'shib qo'ydi
Buni write orqali o'zgartirmoqchi bo'ldim, lekin FD_ISSET ( man7.org/linux/man-pages/man2/select.2.html ) buni qabul qilmaydi
qo'shib qo'ydi muallif Raphaël, manba
Ha (klaviatura kiritishini istamasligim uchun) boshqa (boshqa fayl identifikatori kabi)
qo'shib qo'ydi muallif Raphaël, manba
Men shunga o'xshash yozishni xohladim, lekin FD_ISSET() ishlamasa ham, maxsus fayl identifikatori bilan ishlamaydi. Lseek uchun rahmat, buni tekshirib ko'rmoqchiman
qo'shib qo'ydi muallif Raphaël, manba
FD_ISSET (0, to'siq) qilishni nazarda tutasizmi?
qo'shib qo'ydi muallif tfontain, manba
Stdinni ishlatish klaviaturadan foydalanishga majbur qilishingizni anglatmaydi; Siz o'zingiz ko'rsatgan kabi yozish funktsiyasiga yozishingiz mumkin. Lekin agar "klaviatura kiritishida" siz "standart kirish" degan ma'noni anglatadigan bo'lsak, stdin-ni ishlatishni istamaysiz - faylni ochish yoki fayl yaratish orqali filedescriptorni yaratishingiz kerak. Agar siz ushbu faylni stdin-dan bir xil xatti-harakatlarga ega bo'lishini istasangiz, LSEEK funktsiyasini SEEK_END bilan ko'rib chiqing va bu joyni oxirigacha o'qib chiqing.
qo'shib qo'ydi muallif tfontain, manba

Agar men to'g'ri tushunsam, faqat stdinni o'qiy oladigan dasturga bog'lanmoqchisan. Stdin yozishning ikki yo'li bor: birinchi usul klaviaturadan foydalanish, ikkinchisidir write() dan foydalanish.

#include 
#include 

int         main(void)
{
    char    *s = "what you want to write";
    write(STDIN_FILENO, s, strlen(s));
    return (0);
}

Ushbu dastur sizning klaviaturangiz bilan bir xil tarzda yozishni istagan stdin-da yozadi. Bundan tashqari, siz buyruq qatori interfeysida chop etilgan satrni ko'rasiz.

0
qo'shib qo'ydi
Buni write orqali o'zgartirmoqchi bo'ldim, lekin FD_ISSET ( man7.org/linux/man-pages/man2/select.2.html ) buni qabul qilmaydi
qo'shib qo'ydi muallif Raphaël, manba
Ha (klaviatura kiritishini istamasligim uchun) boshqa (boshqa fayl identifikatori kabi)
qo'shib qo'ydi muallif Raphaël, manba
Men shunga o'xshash yozishni xohladim, lekin FD_ISSET() ishlamasa ham, maxsus fayl identifikatori bilan ishlamaydi. Lseek uchun rahmat, buni tekshirib ko'rmoqchiman
qo'shib qo'ydi muallif Raphaël, manba
FD_ISSET (0, to'siq) qilishni nazarda tutasizmi?
qo'shib qo'ydi muallif tfontain, manba
Stdinni ishlatish klaviaturadan foydalanishga majbur qilishingizni anglatmaydi; Siz o'zingiz ko'rsatgan kabi yozish funktsiyasiga yozishingiz mumkin. Lekin agar "klaviatura kiritishida" siz "standart kirish" degan ma'noni anglatadigan bo'lsak, stdin-ni ishlatishni istamaysiz - faylni ochish yoki fayl yaratish orqali filedescriptorni yaratishingiz kerak. Agar siz ushbu faylni stdin-dan bir xil xatti-harakatlarga ega bo'lishini istasangiz, LSEEK funktsiyasini SEEK_END bilan ko'rib chiqing va bu joyni oxirigacha o'qib chiqing.
qo'shib qo'ydi muallif tfontain, manba